Android后台service保活的一种方式

让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
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值