原作者:“裂缝中的阳光dg”,本文由即时通讯网重新修订并整理发布,感谢原作者的无私分享。
首先在一个实现了JobService的子类的onStartJob方法中执行这项任务,使用JobInfo的Builder方法来设定条件并和实现了JobService的子类的组件名绑定,然后调用系统服务JobScheduler的schedule方法。这样,即便在执行任务之前应用程序进程被杀,也不会导致任务不会执行,因为系统服务JobScheduler会使用bindServiceAsUser的方法把实现了JobService的子类服务启动起来,并执行它的onStartJob方法。
/**JobService,支持5.0以上forcestop依然有效 * * Created by jianddongguo on 2017/7/10. */ @TargetApi(21) public class AliveJobService extends JobService { private final static String TAG = "KeepAliveService"; // 告知编译器,这个变量不能被优化 private volatile static Service mKeepAliveService = null; public static boolean isJobServiceAlive(){ return mKeepAliveService != null; } private static final int MESSAGE_ID_TASK = 0x01; private Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { // 具体任务逻辑 if(SystemUtils.isAPPALive(getApplicationContext(), Contants.PACKAGE_NAME)){ Toast.makeText(getApplicationContext(), "APP活着的", Toast.LENGTH_SHORT) .show(); }else{ Intent intent = new Intent(getApplicationContext(), SportsActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); Toast.makeText(getApplicationContext(), "APP被杀死,重启...", Toast.LENGTH_SHORT) .show(); } // 通知系统任务执行结束 jobFinished( (JobParameters) msg.obj, false ); return true; } }); @Override public boolean onStartJob(JobParameters params) { if(Contants.DEBUG) Log.d(TAG,"KeepAliveService----->JobService服务被启动..."); mKeepAliveService = this; // 返回false,系统假设这个方法返回时任务已经执行完毕; // 返回true,系统假定这个任务正要被执行 Message msg = Message.obtain(mHandler, MESSAGE_ID_TASK, params); mHandler.sendMessage(msg); return true; } @Override public boolean onStopJob(JobParameters params) { mHandler.removeMessages(MESSAGE_ID_TASK); if(Contants.DEBUG) Log.d(TAG,"KeepAliveService----->JobService服务被关闭"); return false; } }
/**JobScheduler管理类,单例模式 * 执行系统任务 * * Created by jianddongguo on 2017/7/10. */ public class JobSchedulerManager { private static final int JOB_ID = 1; private static JobSchedulerManager mJobManager; private JobScheduler mJobScheduler; private static Context mContext; private JobSchedulerManager(Context ctxt){ this.mContext = ctxt; mJobScheduler = (JobScheduler)ctxt.getSystemService(Context.JOB_SCHEDULER_SERVICE); } public final static JobSchedulerManager getJobSchedulerInstance(Context ctxt){ if(mJobManager == null){ mJobManager = new JobSchedulerManager(ctxt); } return mJobManager; } @TargetApi(21) public void startJobScheduler(){ // 如果JobService已经启动或API<21,返回 if(AliveJobService.isJobServiceAlive() || isBelowLOLLIPOP()){ return; } // 构建JobInfo对象,传递给JobSchedulerService JobInfo.Builder builder = new JobInfo.Builder(JOB_ID,new ComponentName(mContext, AliveJobService.class)); // 设置每3秒执行一下任务 builder.setPeriodic(3000); // 设置设备重启时,执行该任务 builder.setPersisted(true); // 当插入充电器,执行该任务 builder.setRequiresCharging(true); JobInfo info = builder.build(); //开始定时执行该系统任务 mJobScheduler.schedule(info); } @TargetApi(21) public void stopJobScheduler(){ if(isBelowLOLLIPOP()) return; mJobScheduler.cancelAll(); } private boolean isBelowLOLLIPOP(){ // API< 21 return Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP; } }
<--! AliveJobService需要BIND_JOB_SERVICE权限--> <service android:name=".service.AliveJobService" android:permission="android.permission.BIND_JOB_SERVICE"/>
注:如果遇到深度定制机型,这就要看运气了...
1.gif (682.22 KB, 下载次数: 1992)
下载附件 保存到相册
7 年前 上传
/** 华为接收器子类,用于接收推送消息 * * Created by jianddongguo on 2017/7/10. */ public class MyHwPushReceiver extends PushEventReceiver{ private final static String TAG = "MyHwPushReceiver"; /** * pushToken申请成功后,会自动回调该方法 * 应用通过该方法获取token(必须实现) * */ @Override public void onToken(Context context, String token, Bundle bundle) { Log.i(TAG,"连接到华为推送服务器,token="+token); } /** * 推送消息下来时会自动回调onPushMsg方法 * 用于接收透传消息(必须实现) * */ @Override public boolean onPushMsg(Context context, byte[] msgBytes, Bundle bundle) { if(Contants.DEBUG){ try { Log.i(TAG,"接收透传消息:"+new String(msgBytes,"UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } // 启动应用 return false; } /** * 连接状态的回调方法 * */ @Override public void onPushState(Context context, boolean connectState) { Log.i(TAG,"是否连接到华为推送服务器:"+(connectState?"connected":"disconnected")); } /** * 该方法会在设置标签、LBS信息之后,点击打开通知栏消息 * 点击通知栏上的按钮之后被调用,由业务决定是否调用该函数。 * Event类型: * NOTIFICATION_OPEMED,通知栏中的通知被点击打开 * NOTIFICATION_CLICK_BTN,通知栏中通知上的按钮被点击 * PLUGINRSP,标签上报回应 * */ @Override public void onEvent(Context context, Event event, Bundle bundle) { super.onEvent(context, event, bundle); } }
/** * 华为推送控制类 * * Created by jianddongguo on 2017/7/15. */ public class HwPushManager { private static HwPushManager mPushManager; private Context mContext; private HwPushManager(Context mContext){ this.mContext = mContext; } public static HwPushManager getInstance(Context mContext){ if(mPushManager == null){ mPushManager = new HwPushManager(mContext); } return mPushManager; } /**向服务器请求Token * 前提是已经在华为开发者联盟注册本应用,并申请、审核通过Push权益 * */ public void startRequestToken(){ PushManager.requestToken(mContext); } /** * 是否接收服务器传递过来的透传消息 * */ public void isEnableReceiveNormalMsg(boolean isEnable){ PushManager.enableReceiveNormalMsg(mContext,isEnable); } /** * 是否接收自呈现消息 * */ public void isEnableReceiverNotifyMsg(boolean isEnable){ PushManager.enableReceiveNotifyMsg(mContext,isEnable); } }
<!-- 必需的权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- 第三方相关 :接收Push消息(注册、Push消息、Push连接状态、标签,LBS上报结果)广播 --> <receiver android:name=".receiver.MyHwPushReceiver" > <intent-filter> <!-- 必须,用于接收token--> <action android:name="com.huawei.android.push.intent.REGISTRATION" /> <!-- 必须,用于接收消息--> <action android:name="com.huawei.android.push.intent.RECEIVE" /> <!-- 可选,用于点击通知栏或通知栏上的按钮后触发onEvent回调--> <action android:name="com.huawei.android.push.intent.CLICK" /> <!-- 可选,查看push通道是否连接,不查看则不需要--> <action android:name="com.huawei.intent.action.PUSH_STATE" /> <!-- 可选,标签、地理位置上报回应,不上报则不需要 --> <action android:name="com.huawei.android.push.plugin.RESPONSE" /> </intent-filter> <meta-data android:name="CS_cloud_ablitity" android:value="@string/hwpush_ability_value"/> </receiver> <!-- 备注:Push相关的android组件需要添加到业务的AndroidManifest.xml, Push相关android组件运行在另外一个进程是为了防止Push服务异常而影响主业务 --> <!-- PushSDK:PushSDK接收外部请求事件入口 --> <receiver android:name="com.huawei.android.pushagent.PushEventReceiver" android:process=":pushservice" > <intent-filter> <action android:name="com.huawei.android.push.intent.REFRESH_PUSH_CHANNEL" /> <action android:name="com.huawei.intent.action.PUSH" /> <action android:name="com.huawei.intent.action.PUSH_ON" /> <action android:name="com.huawei.android.push.PLUGIN" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <data android:scheme="package" /> </intent-filter> </receiver> <receiver android:name="com.huawei.android.pushagent.PushBootReceiver" android:process=":pushservice" > <intent-filter> <action android:name="com.huawei.android.push.intent.REGISTER" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> <meta-data android:name="CS_cloud_version" android:value="\u0032\u0037\u0030\u0035" /> </receiver> <!-- PushSDK:Push服务 --> <service android:name="com.huawei.android.pushagent.PushService" android:process=":pushservice" > </service> <!-- PushSDK:富媒体呈现页面,用于呈现服务器下发的富媒体消息 --> <!-- locale|layoutDirection 切换语言后不重新创建activity --> <activity android:name="com.huawei.android.pushselfshow.richpush.RichPushActivity" android:process=":pushservice" android:theme="@style/hwpush_NoActionBar" android:configChanges="orientation|screenSize|locale|layoutDirection" android:screenOrientation="portrait"> <meta-data android:name="hwc-theme" android:value="androidhwext:style/Theme.Emui"/> <intent-filter> <action android:name="com.huawei.android.push.intent.RICHPUSH" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <activity android:name="com.huawei.android.pushselfshow.permission.RequestPermissionsActivity" android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar" android:launchMode="singleTop" android:screenOrientation="portrait" android:configChanges="orientation|screenSize|locale|layoutDirection" android:exported="false"> </activity>
2.png (30.48 KB, 下载次数: 2091)
3.gif (485.15 KB, 下载次数: 1997)
来源:即时通讯网 - 即时通讯开发者社区!
轻量级开源移动端即时通讯框架。
快速入门 / 性能 / 指南 / 提问
轻量级Web端即时通讯框架。
详细介绍 / 精编源码 / 手册教程
移动端实时音视频框架。
详细介绍 / 性能测试 / 安装体验
基于MobileIMSDK的移动IM系统。
详细介绍 / 产品截图 / 安装体验
一套产品级Web端IM系统。
详细介绍 / 产品截图 / 演示视频
引用此评论
引用:大尾巴鱼 发表于 2017-11-01 16:25 其实在国内最佳实践应该是接入各个平台的推送服务吧,比如检测如果是华为手机就注册华为的推送服务,小米手 ...
引用:SingleInstance 发表于 2017-11-06 16:53 关键问题嘛,即使让你钻空子找到了个法子,定制ROM轻易就能把你禁了,系统是不允许有这么流氓的软件存在的 ...
引用:laorencel 发表于 2017-11-16 11:02 准备用上试试,ov手机太牛,app时间不长就会被干掉
引用:北方竹子 发表于 2017-12-28 10:05 被推送服务搞得不要不要的 试试看
引用:liam 发表于 2018-06-04 09:04 高版本越来越难了
引用:小马哥 发表于 2018-07-11 16:14 保活没有终极大招,经常被客户追着问,“人家微信、QQ都可以,为啥你们的APP非得加到手机白名单”,哎
精华主题数超过100个。
连续任职达2年以上的合格正式版主
为论区做出突出贡献的开发者、版主等。
Copyright © 2014-2024 即时通讯网 - 即时通讯开发者社区 / 版本 V4.4
苏州网际时代信息科技有限公司 (苏ICP备16005070号-1)
Processed in 0.213875 second(s), 46 queries , Gzip On.