要让Android在锁屏下继续运行,用如下的代码即可实现。

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
wl.acquire();
   ..screen will stay on during this section..
wl.release();

在实现IP摄像头锁屏下运行时,发现这个代码没效果,锁屏后程序还是会断开连接。程序是在onCreate中调用acquire()获得WakeLock的,而在onDestory中Release()掉,并且在xml中加入了相应权限,运行也没报错,按理说有效果才对。

跟踪程序后发现,每次锁屏onDestory都会被调用,所以WakeLock就给Release了。用onDestory和锁屏两个作为关键词谷歌了一下,发现这个是由于程序在横屏下锁屏后会被“竖屏”,然后如果Activity不加android:configChanges=”orientation”就会经历一次销毁再创建的过程……

参考如下  blog.csdn.net/terrantian/article/details/18670381

解决方法如下:

在对应的Activity加入android:configChanges=”orientation|screenSize”即可。最后实现了IP摄像头在锁屏下继续工作!

经过一个多星期的努力,IP摄像头5.3版终于诞生的,这个版本的网页端采用了全新的界面,感谢bootstrap,让它可以适配PC端到移动端浏览器来查看视频流。这个版本支持通过网页来控制手机摄像头的分辨率,拍照,闪光灯,对焦,甚至前后摄像头切换。最后,这个版本支持锁屏下广播视频流,按一下电源键,锁屏,屏幕关闭,更加省电!

献上一段演示视频:

锁屏下 IP摄像头 仍然在工作
锁屏下 IP摄像头 仍然在工作

网页端控制
网页端控制

新版变化
1.全新的浏览器查看页面,响应式布局,支持移动版Chrome
2.浏览器端支持摄像头控制,包括分辨率、闪光灯、对焦以及前后摄像头切换等
3.支持锁屏下使用,更加省电。按下电源键锁屏后程序将继续广播视频流。
4.支持浏览器端拍照,点击页面中的‘快照’按钮即可
5.改善程序稳定性以及代码速度优化

各大应用商店将陆续上线,请认准5.3版 IP摄像头 →→右边栏有下载链接:)

发现《蓝牙串口》《TCP连接》的十六进制编辑框在输入时还要自己注意添加空格太不智能了,又容易出错。所以就想着在每输入两个字符后自动加入一个空格(两个字符代表一个十六进制数,刚好可以转成一个BYTE),然后删除字符时,可以自动删除空格(不懂怎么表述,运行一下代码就知道了)。

方法:使用EditText的addTextChangedListener接口,并实现TextWatcher。具体实现代码如下:

TextWatcher autoAddSpaceTextWatcher = new TextWatcher() {
	@Override
	public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {}
 
	@Override
	public void onTextChanged(CharSequence s, int start, int before, int count) {
		if (count == 1) {
			if ((s.length() + 1) % 3 == 0) {
				setText(s + " ");
				setSelection(s.length() + 1);
			}
		}  else if (count == 0) {
			if (s.length() > 0 && s.length() % 3 == 0) {
				setText(s.subSequence(0, s.length() - 1));
				setSelection(s.length() - 1);
			}
		}
	}
 
	@Override
	public void afterTextChanged(Editable editable) {}
};

最后调用addTextChangedListener传入autoAddSpaceTextWatcher即可!赶紧去体验新版《蓝牙串口》和《TCP连接》的十六进制输入吧!

最近在更新《轻松编辑》《IP摄像头》的网页服务器部分时,遇到了两个String的问题。

第一个是获取String占用的内存字节数,自己想当然直接用length()函数取得了长度了,可到了socket发送数据的时候总是发送不完整(字符串中包含中文),后面Debug之后才发现length得到的是字符数,而不是内存中的字节数,一个中文在UTF8编码下要占用3个字节,自然得到的长度变短了,所以发送不完整。正确做法是getBytes(),再在返回的数组中取length。

第二个是截取String指定区间的子字符串,函数substring (int start, int end)。比如要取索引2到5这4个字符,直接substring (2, 5)……然后得到的是索引2到4三个字符组成的字符串,索引5的那个字符并没有出现,后面查了一下谷歌,才发现substring (int start, int end)返回的字符串不包含索引end的字符!!!所以正确的应该是substring (2, 6)。

发现了这两个特别注意的地方,就是不知道先前的代码有没出现过这两个错误。

在开发《轻松编辑》5.1版的快速打开文本文件时,遇到了如何快速获取SD卡上所有文本文件的问题。查了API,发现MediaStore可以使用。MediaStore可以获取音乐、视频和图片等,在API level 大于11后还可以获取其它文件,比如文本,或者doc,pdf。

相关代码如下:

@TargetApi(11)
private void refreshList(){
	String[] columns = new String[] {
		MediaStore.Files.FileColumns.TITLE,
		MediaStore.Files.FileColumns.DATA
	};
	Uri uri = MediaStore.Files.getContentUri("external");
	String selection = "(" + MediaStore.Files.FileColumns.MIME_TYPE + "=='text/plain')";
	Cursor c = getContentResolver().query(uri, columns, selection, null, MediaStore.Files.FileColumns.SIZE + " DESC");
	if (c == null) {
		return;
	}
 
	if (c.moveToFirst()) {
		int dataIndex = c.getColumnIndex(MediaStore.Files.FileColumns.DATA);
		int titleIndex = c.getColumnIndex(MediaStore.Files.FileColumns.TITLE);
		do {
 
			c.getString(titleIndex); // 获取文件名,不包含扩展名
			c.getString(dataIndex);  // 获取文件实际路径
 
		} while (c.moveToNext()); // 循环获取文件
	}
}

注意:MediaStore.Files这个类要到API Level 11才能使用,这就是《轻松编辑》在Android 3.0版本以下不能启用快速打开文本的原因。其实这个可以解决的,比如在android 3.0以下用手动来获取,可如果SD卡上文件很多的话,这个时间就很漫长了,所以还是不加好。