Android后台service保活的一种方式

来源:互联网 发布:剑三最美萝莉脸型数据 编辑:程序博客网 时间:2024/06/15 09:44

让App的service在后台长久运行其实是很流氓的做法,但是“刚性”的需求就摆在那里。。。
各种招式尝试了一圈,发现一个目前来看还算靠谱的方法,详情如下。

方案思想
监听手机的锁屏和亮屏事件,在锁屏时启动一个透明的Activity,在亮屏时将Activity销毁掉(该Activity在整个过程中用户无感知)。
本质:使进程的优先级在锁屏期间由4提升为1。

具体实现
1、先定义一个Activity,设置其大小为1像素。

public class KeepAlive_Activity extends Activity{    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        //只有左上角的一个点,主要为了使用户无感知        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);        //通过EventBus来接收消息         EventBus.getDefault().register(this);    }    @Override    protected void onDestroy()    {        super.onDestroy();        EventBus.getDefault().unregister(this);    }    // EventBus ------------------------------    @Subscribe (threadMode = ThreadMode.MAIN)    public void onMessageEvent(EventMessage msg)    {        int msgCode = msg.msgCode;        switch (msgCode)        {            case Event_Finish_KeepAliveActivity:                KeepAlive_Activity.this.finish();                break;            default:                break;        }    }}

2、在AndroidManifest中设置属性,排除该Activity在RecentTask中的显示:

<activity android:name=".KeepAlive_Activity"          android:configChanges="keyboardHidden|orientation"          android:excludeFromRecents="true"          android:exported="false"          android:finishOnTaskLaunch="false"          android:launchMode="singleInstance"          android:screenOrientation="portrait"          android:theme="@style/AliveActivity_style"/>

3、在styles.xml中设置该Activity为透明:

<style name="AliveActivity_style">    <item name="android:windowBackground">@android:color/transparent</item>    <item name="android:windowIsTranslucent">true</item>    <item name="android:background">@null</item></style>

4、此Activity的启动与销毁

/* 注册广播,监听手机屏幕事件 */myReceiver = new MyReceiver();IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_ON); //亮屏filter.addAction(Intent.ACTION_SCREEN_OFF); //锁屏、黑屏this.registerReceiver(myReceiver, filter);
class MyReceiver extends BroadcastReceiver{  @Override  public void onReceive(Context context, Intent intent)  {     String action = intent.getAction();     if (action.equals(Intent.ACTION_SCREEN_OFF)) //锁屏、黑屏     {         //启动保活Activity         Intent aIntent = new Intent(XX_Activity.this, KeepAlive_Activity.class);         startActivity(aIntent);     }      else if (action.equals(Intent.ACTION_SCREEN_ON)) //亮屏     {         //移除保活Activity         EventBus.getDefault().post(new EventMessage(Event_Finish_KeepAliveActivity, ""));     }  }}

receiver记得解绑

@Override    protected void onDestroy()    {        super.onDestroy();        EventBus.getDefault().unregister(this);        if (myReceiver != null)        {            this.unregisterReceiver(myReceiver);            myReceiver = null;        }    }

更多
1、方案参考至 http://blog.csdn.net/u011622280/article/details/52311344,略有调整。
原方案是监听的锁屏(ACTION_SCREEN_OFF)和解锁(ACTION_USER_PRESENT)两个事件,略有瑕疵,因为锁屏和解锁并不总是成对出现,比如App内的某处跳转到了打电话,手机靠近耳朵,手机锁屏,电话打完离开耳朵,手机亮屏(但并没有解锁),这时点击挂电话是无效的(因为那个透明的Activity还浮在上面)。
锁屏(ACTION_SCREEN_OFF)和亮屏(ACTION_SCREEN_ON)是成对出现的,监听它们会比较安全。
2、该方案只能增强App后台运行优先级,避免被系统销毁,若用户手动结束或杀掉App,后台service仍然可以被销毁。
3、方案中的消息传递采用了EventBus,也可以采用其它方式。

1 0
原创粉丝点击