天天看点

最近遇到的几个Android疑难问题

1、Service运行2小时之后被系统关闭

我的Service在真机上运行了大约1~2小时之后,被系统关闭然后重新创建。

onStartCommand() 返回的是 START_STICKY,但是,当系统重新创建该Service之后,只调用了 onCreate(),

并没有调用Service 的 onStartCommand()。

解决办法: 把所有初始化操作放入 onCreate()

2、Camera被其他进程占用时,调用 Camera.open() 导致进程异常终止

解决办法就是用 try{...} Exception {...}

把一切异常都湮灭

关于摄像头,最近我的手机升级到了4.0.4 (Nexus S)之后,用原来的代码打开闪光灯的方法失灵了,原来的代码如下:

Camera c = Camera.open();
Camera.Parameters p = c.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
c.setParameters(p);
c.startPreview();
           

在网上搜了一下,有人已经克服这个问题了,但是没人讲他们是怎么解决这个问题的。

我经过几番尝试,终于弄明白为什么以上代码在4.0以后系统无法打开闪光灯了:

从 API 11 开始, Camera 类的API有一些调整,需要把 Camera 所需的各项参数都设置好了才行,以上代码只设了一个

flash mode,缺了很多东西,所以打不开闪光灯。 以下代码是我在4.0系统上测试好了,可以打开闪光灯的代码:

Camera c = Camera.open();
Camera.Parameters p = c.getParameters();
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
List<Integer> rates = params.getSupportedPreviewFrameRates();
p.setPreviewFrameRate(rates.get(0));
p.setPreviewSize(sizes.get(0).width, sizes.get(0).height);
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
p.setFocusMode(Parameters.FOCUS_MODE_AUTO);
c.setParameters(params);

try {
	if (  Build.VERSION.SDK_INT >= 11 ) {
		c.setPreviewTexture(new SurfaceTexture(0));
	}
	c.startPreview();
}
catch(IOException e) {
	e.printStackTrace();
}
           

3、如何在Service中更新App Widget:

典型代码如下:

AppWidgetManager mgr = AppWidgetManager.getInstance(this);

        int[] ids = mgr.getAppWidgetIds(new ComponentName(this, FlashlightWidgetProvider.class));

        for ( int id : ids ) {

            RemoteViews views = new RemoteViews(getPackageName(), R.layout.widget_flashlight);

            操作views(把views看做App Widget)

            mgr.updateAppWidget(id, views);

        }

4、PopupWindow 如何设置动画

在 res/values 下新建一个xml文件,文件名任意,例如res/values/styles.xml,

创建一个style资源,例如:

<style name="AnimationPopup">
    <item name="@android:windowEnterAnimation">@anim/popup_show</item>
    <item name="@android:windowExitAnimation">@anim/popup_hide</item>
</style>

           

这个style资源应该包含两个item,一个用于出现,另一个用于消失。这两个item都是动画资源。

然后,调用 PopupWindow.setAnimationStyle(int),把R.style.AnimationPopup传进来即可。

5、PopupWindow.showXXX() 之后,窗口不显示

是因为没有设置PopupWindow的窗口大小,可以调用 PopupWindow.setWindowLayoutMode(WRAP_CONTENT, WRAP_CONTENT)

PopupWindow的窗口默认大小为0.

在Activity退出之前,应该主动调用 PopupWindow.dismiss(),否则会报告 window leak 异常。

6、如何实现开机启动

Android系统每次启动的时候都会广播一个Intent,只要在自己的程序中创建一个BroadcastReceiver,

接收这个Intent,然后启动自己的服务即可。

例如,在AndroidManifest.xml 中定义receiver:

<receiver android:name=".service.BootReceiver">

    <intent-filter>

    <!-- 系统启动完成后会调用-->

    <action android:name="android.intent.action.BOOT_COMPLETED">

    </action>

    </intent-filter>

</receiver>

也可以动态注册这个receiver

需要权限: android.permission.RECEIVE_BOOT_COMPLETED

7、用 Resources.openRawResourceFd(int) 得到的文件描述符传给

MediaPlayer.setDataSource(FileDescriptor fd) 似乎不起作用,要用 MediaPlayer.setDataSource(FileDescriptor fd, long offset, long length)

才可以。

8、AdapterView经常遇到list item的onItemClick不起作用的问题,如何解决?

网上查资料说要把所有内部的view的focusable设置为false,或者给root view设置descendantFocusability为不让所有后代view得到focus。

本人尝试了这些方法,依旧没有解决问题。最后采取一种“愚蠢”办法,给每个item view设置了View.OnClickListener()。这样一来,onClick()必须找到哪个item被点击。

TODO:等我找到更好的办法之后,再记录在这里。