在完成了基本的播放功能后,发现一个APP存在的bug
音乐播放到一半的时候突然整个app进程被杀死了。
我打开手机发现后台的服务也没有在运行。
查看相关资料后发现,有些手机有熄屏后杀死非白名单内的APP的功能
这样做是为了省电以及节省下不必要的内存
但这样一来我的音乐播放器就无法在熄屏后播放了
这肯定是不行的。
但是我发现像 QQ、微信之类的就没有在熄屏后被杀,
用户也没有手动将其加入系统白名单中。
后来查找资料得知这种情况是 QQ和微信已经加入到系统的白名单中了,
当然不需要用户手动添加了。
不过这已经不是技术人员可以解决的了,需要双方的商务洽谈了。
最后我想到的办法,就是一像素进程保活了。
通过这种方式才能让我的音乐播放器在熄屏后继续播放,
哪怕用户没有将它加入白名单。
具体的做法如下
第一步:
注册监听屏幕的广播,注意,这个广播应该在APP的首页注册
而不是音乐播放界面,
因为一个APP只要存在,它的首页肯定是没有被finish掉的
而播放界面可以finish,但是音乐仍然可以继续在service后台播放
监听屏幕的广播类如下:
/** * Created by Administrator on 2017/7/14. * 监听屏幕状态的广播 */ public class OnePixelReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { //屏幕关闭启动1像素Activity Log.d("print", "关"); Intent it = new Intent(context, OnePiexlActivity.class); it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(it); } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { //屏幕打开 结束1像素 Log.d("print", "开"); context.sendBroadcast(new Intent("finish")); Intent main = new Intent(Intent.ACTION_MAIN); main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); main.addCategory(Intent.CATEGORY_HOME); context.startActivity(main); } } }
然后在首页注册这个广播
//监听屏幕状态的广播 private OnePixelReceiver mOnepxReceiver;
mOnepxReceiver = new OnePixelReceiver(); IntentFilter intentFilter2 = new IntentFilter(); intentFilter2.addAction("android.intent.action.SCREEN_OFF"); intentFilter2.addAction("android.intent.action.SCREEN_ON"); intentFilter2.addAction("android.intent.action.USER_PRESENT"); registerReceiver(mOnepxReceiver, intentFilter2);
第二步,创建一个1像素的Activity
监听这个屏幕状态的广播
配置清单注册
<!-- 1像素的activity用来给进程保活 --> <activity android:name=".activity.OnePiexlActivity" android:screenOrientation="portrait" android:theme="@style/OnePixelActivity" />
Activity代码:
/** * 1像素的activity用来给播放音乐进程保活 */ public class OnePiexlActivity extends Activity { private BroadcastReceiver endReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //设置1像素 Window window = getWindow(); window.setGravity(Gravity.LEFT | Gravity.TOP); WindowManager.LayoutParams params = window.getAttributes(); params.x = 0; params.y = 0; params.height = 1; params.width = 1; window.setAttributes(params); //结束该页面的广播 endReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { finish(); } }; registerReceiver(endReceiver, new IntentFilter("finish")); //检查屏幕状态 checkScreen(); } @Override protected void onResume() { super.onResume(); checkScreen(); } /** * 检查屏幕状态 isScreenOn为true 屏幕“亮”结束该Activity */ private void checkScreen() { PowerManager pm = (PowerManager) OnePiexlActivity.this.getSystemService(Context.POWER_SERVICE); boolean isScreenOn = pm.isScreenOn(); if (isScreenOn) { finish(); } } }
第三步,这里注意,我们还需要设置1像素activity为透明,
不然可能会影响体验,但是影响不大,1像素毕竟是挑战视力的存在。
<!--1像素的activity设置为透明--> <style name="OnePixelActivity" parent="android:Theme.Holo.Light.NoActionBar">//无标题 <item name="android:windowIsTranslucent">true</item>//透明 </style>
这样一来APP在播放音乐的时候就不会被后台杀死了
这个bug也就解决了。
总结与反思:
国内的android生态目前来说已经有所改观
但并不代表APP的运行环境就一定会好起来
不同厂商间的相互竞争,以及整个大环境的氛围
都在决定未来android生态的走向
或许不是每个APP 都能像QQ、微信那样被加入白名单
但我始终认为,客户真正需要的才是最好的。
一个符合客户需求的功能,不该被android系统kill掉
但是客户需求不是厂商说了算的,
是需要时间去证明的。
所以目前来看,采用这种1像素保活的方式
我个人是不太赞成的。
要不是因为开发的是音乐播放器,
我是不太喜欢这样强制的占用内存的措施的。
这点也可以看出,
APP的开发更多的涉及到厂商和软件公司之间的利益
有些时候是我们开发人员和客户无法左右的。