企业局域网视频网站建设,网络电商推广方案,深圳 网站设计师 招聘,如何建立内部网站Android进程保活主要包括两个方面#xff1a; 提高进程的优先级#xff0c;降低被杀死的概率在进程被杀死后拉活 1.进程优先级
Android 系统将尽量长时间地保持应用进程#xff0c;但为了新建进程或运行更重要的进程#xff0c;最终需要移除旧进程来回收内存。 为了确定保… Android进程保活主要包括两个方面 提高进程的优先级降低被杀死的概率在进程被杀死后拉活 1.进程优先级
Android 系统将尽量长时间地保持应用进程但为了新建进程或运行更重要的进程最终需要移除旧进程来回收内存。 为了确定保留或终止哪些进程系统会根据进程中正在运行的组件以及这些组件的状态将每个进程放入“重要性层次结构”中。 必要时系统会首先消除重要性最低的进程然后是重要性略低的进程依此类推以回收系统资源。
重要性层次结构一共有 5 级。以下列表按照重要程度列出了各类进程第一个进程最重要将是最后一个被终止的进程
1.1 前台进程
用户当前操作所必需的进程。如果一个进程满足以下任一条件即视为前台进程
托管用户正在交互的 Activity已调用 Activity 的 onResume() 方法托管某个 Service后者绑定到用户正在交互的 Activity托管正在“前台”运行的 Service服务已调用 startForeground()托管正执行一个生命周期回调的 ServiceonCreate()、onStart() 或 onDestroy()托管正执行其 onReceive() 方法的 BroadcastReceiver
通常在任意给定时间前台进程都为数不多。只有在内存不足以支持它们同时继续运行这一万不得已的情况下系统才会终止它们。 此时设备往往已达到内存分页状态因此需要终止一些前台进程来确保用户界面正常响应。
1.2 可见进程
没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。 如果一个进程满足以下任一条件即视为可见进程
托管不在前台、但仍对用户可见的 Activity已调用其 onPause() 方法。例如如果前台 Activity 启动了一个对话框允许在其后显示上一 Activity则有可能会发生这种情况。托管绑定到可见或前台Activity 的 Service。
可见进程被视为是极其重要的进程除非为了维持所有前台进程同时运行而必须终止否则系统不会终止这些进程。
1.3 服务进程
正在运行已使用 startService() 方法启动的服务且不属于上述两个更高类别进程的进程。
尽管服务进程与用户所见内容没有直接关联但是它们通常在执行一些用户关心的操作例如在后台播放音乐或从网络下载数据。因此除非内存不足以维持所有前台进程和可见进程同时运行否则系统会让服务进程保持运行状态。
1.4 后台进程
包含目前对用户不可见的 Activity 的进程已调用 Activity 的 onStop() 方法。
这些进程对用户体验没有直接影响系统可能随时终止它们以回收内存供前台进程、可见进程或服务进程使用。 通常会有很多后台进程在运行因此它们会保存在 LRU 最近最少使用列表中以确保包含用户最近查看的 Activity 的进程最后一个被终止。如果某个 Activity 正确实现了生命周期方法并保存了其当前状态则终止其进程不会对用户体验产生明显影响因为当用户导航回该 Activity 时Activity 会恢复其所有可见状态。 有关保存和恢复状态的信息请参阅 Activity文档。
1.5 空进程
不含任何活动应用组件的进程。
保留这种进程的的唯一目的是用作缓存以缩短下次在其中运行组件所需的启动时间。 为使总体系统资源在进程缓存和底层内核缓存之间保持平衡系统往往会终止这些进程。 2.Android进程回收策略LowMemoryKiller
为什么引入LowMemoryKiller
进程的启动分冷启动和热启动当用户退出某一个进程的时候并不会真正的将进程退出而是将这个进程放到后台以便下次启动的时候可以马上启动起来这个过程名为热启动这也是Android的设计理念之一。这个机制会带来一个问题每个进程都有自己独立的内存地址空间随着应用打开数量的增多,系统已使用的内存越来越大就很有可能导致系统内存不足。为了解决这个问题系统引入LowmemoryKiller(简称lmk)管理所有进程根据一定策略来kill某个进程并释放占用的内存保证系统的正常运行。
LowMemoryKiller的基本原理
所有应用进程都是从zygote孵化出来的记录在AMS中mLruProcesses列表中由AMS进行统一管理AMS中会根据进程的状态更新进程对应的oom_adj值这个值会通过文件传递到kernel中去kernel有个低内存回收机制在内存达到一定阀值时会触发清理oom_adj值高的进程腾出更多的内存空间。
什么是oom_adj
它是linux内核分配给每个系统进程的一个值代表进程的优先级进程回收机制就是根据这个优先级来决定是否进行回收。对于oom_adj的作用你只需要记住以下几点即可
进程的oom_adj越大表示此进程优先级越低越容易被杀回收越小表示进程优先级越高越不容易被杀回收普通app进程的oom_adj0,系统进程的oom_adj才可能0
minfree 阈值
存放6个数值每个数表示内存页面数,单位是page(一个页面4kb)
查看方式
adb shell
su
cat /sys/module/lowmemorykiller/parameters/minfree得到的数值为18432,23040,27648,32256,36864,46080这6个数值分别代表android系统回收6种进程的阈值这么看不方便查看转换为M会更直观这6个数值的单位为page 1page 4K,所以通过 数值*4/1024就能转换为M:72M,90M,108M,126M,144M,180M也就是说1.前台进程foreground2.可见进程visible3.次要服务secondary server4.后台进程hidden5.内容供应节点content provider6.空进程empty这6类进程进行回收的内存阈值分别为72M,90M,108M,126M,144M,180M
oom_adj值
oom_adj的值越小进程的优先级越高
获取进程oom_adj方式
cat /proc/进程id/oom_adjadj级别值解释UNKNOWN_ADJ16预留的最低级别一般对于缓存的进程才有可能设置成这个级别CACHED_APP_MAX_ADJ15缓存进程空进程在内存不足的情况下就会优先被killCACHED_APP_MIN_ADJ9缓存进程也就是空进程SERVICE_B_ADJ8不活跃的进程PREVIOUS_APP_ADJ7切换进程HOME_APP_ADJ6与Home交互的进程SERVICE_ADJ5有Service的进程HEAVY_WEIGHT_APP_ADJ4高权重进程BACKUP_APP_ADJ3正在备份的进程PERCEPTIBLE_APP_ADJ2可感知的进程比如那种播放音乐VISIBLE_APP_ADJ1可见进程FOREGROUND_APP_ADJ0前台进程PERSISTENT_SERVICE_ADJ-11重要进程PERSISTENT_PROC_ADJ-12核心进程SYSTEM_ADJ-16系统进程NATIVE_ADJ-17系统起的Native进程
上表的数字可能在不同系统会有一定的出入
内存阈值在不同的手机上不一样一旦低于该值,Android便开始按顺序关闭进程. 因此Android开始结束优先级最低的空进程即当可用内存小于180MB(46080) 3.提高进程优先级方案
3.1 Activity提权降低oom_adj
原理
监控手机锁屏解锁事件在屏幕锁屏时启动1个像素透明的 Activity在用户解锁时将 Activity 销毁掉从而达到提高进程优先级的作用可以使进程的优先级在屏幕锁屏时间由4提升为最高优先级1。
代码实现
public class KeepManager {private static final KeepManager ourInstance new KeepManager();public static KeepManager getInstance() {return ourInstance;}private KeepManager() {}private KeepReceiver keepReceiver;private WeakReferenceActivity mKeepActivity;/*** 注册* param context*/public void registerKeepReceiver(Context context){IntentFilter filter new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_OFF);filter.addAction(Intent.ACTION_SCREEN_ON);keepReceiver new KeepReceiver();context.registerReceiver(keepReceiver, filter);}/*** 反注册* param context*/public void unRegisterKeepReceiver(Context context){if (null ! keepReceiver) {context.unregisterReceiver(keepReceiver);}}/*** 启动1个像素的KeepActivity* param context*/public void startKeep(Context context) {Intent intent new Intent(context, KeepActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(intent);}/*** finish1个像素的KeepActivity*/public void finishKeep() {if (null ! mKeepActivity) {Activity activity mKeepActivity.get();if (null ! activity) {activity.finish();}mKeepActivity null;}}public void setKeepActivity(KeepActivity mKeepActivity) {this.mKeepActivity new WeakReferenceActivity(mKeepActivity);}
}public class KeepReceiver extends BroadcastReceiver {private static final String TAG KeepReceiver;Overridepublic void onReceive(Context context, Intent intent) {String action intent.getAction();Log.e(TAG, receive: action);if (TextUtils.equals(action, Intent.ACTION_SCREEN_OFF)) {//灭屏 开启1px activityKeepManager.getInstance().startKeep(context);} else if (TextUtils.equals(action, Intent.ACTION_SCREEN_ON)) {//亮屏 关闭KeepManager.getInstance().finishKeep();}}
}3.2 Service提权降低oom_adj
创建一个前台服务用于提高app在按下home键之后的进程优先级startForeground(ID,Notification)使Service成为前台Service。 前台服务需要在通知栏显示一条通知
API level18参数2设置为newNotification(),图标不会显示API level18 API level26在需要提权的service A启动一个InnerService两个服务都startForeground且绑定相同的idStop掉InnerService通知栏图标被移除API level26必须手动创建通知栏无法移除通知栏图标startForegroundService代替了startService
代码实现
public class ForegroundService extends Service {NullableOverridepublic IBinder onBind(Intent intent) {return null;}Overridepublic void onCreate() {super.onCreate();if (Build.VERSION.SDK_INT Build.VERSION_CODES.O) {NotificationChannel channel new NotificationChannel(deamon, deamon,NotificationManager.IMPORTANCE_LOW);NotificationManager manager (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);if (manager null)return;manager.createNotificationChannel(channel);Notification notification new NotificationCompat.Builder(this, deamon).setAutoCancel(true).setCategory(Notification.CATEGORY_SERVICE).setOngoing(true).setPriority(NotificationManager.IMPORTANCE_LOW).build();startForeground(10, notification);} else if (Build.VERSION.SDK_INT Build.VERSION_CODES.JELLY_BEAN_MR2) {//如果 18 以上的设备 启动一个Service startForeground给相同的id//然后结束那个ServicestartForeground(10, new Notification());startService(new Intent(this, InnnerService.class));} else {startForeground(10, new Notification());}}public static class InnnerService extends Service {Overridepublic void onCreate() {super.onCreate();startForeground(10, new Notification());stopSelf();}NullableOverridepublic IBinder onBind(Intent intent) {return null;}}
}4.进程杀死后拉活方案
4.1 系统广播拉活
在发生特定系统事件时系统会发出广播通过在 AndroidManifest 中静态注册对应的广播监听器即可在发生响应事件时拉活。但是从android 7.0开始对广播进行了限制而且在8.0更加严格8.0以后应该是没用了。
官网介绍
4.2 “全家桶”拉活
有多个app在用户设备上安装只要开启其中一个就可以将其他的app也拉活。比如手机里装了手Q、QQ空间、兴趣部落等等那么打开任意一个app后其他的app也都会被唤醒。
普通小厂不太现实没有一系列的app
4.3 Service机制(Sticky)拉活
将 Service 设置为 START_STICKY利用系统机制在 Service 挂掉后自动拉活
START_STICKY “粘性”。如果service进程被kill掉保留service的状态为开始状态但不保留递送的intent对象。随后系统会尝试重新创建service由于服务状态为开始状态所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service那么参数Intent将为null。START_NOT_STICKY “非粘性的”。使用这个返回值时如果在执行完onStartCommand后服务被异常kill掉系统不会自动重启该服务。START_REDELIVER_INTENT 重传Intent。使用这个返回值时如果在执行完onStartCommand后服务被异常kill掉系统会自动重启该服务并将Intent的值传入。START_STICKY_COMPATIBILITY START_STICKY的兼容版本但不保证服务被kill后一定能重启。
只要 targetSdkVersion 不小于5就默认是 START_STICKY。但是某些ROM 系统不会拉活。并且经过测试Service 第一次被异常杀死后很快被重启第二次会比第一次慢第三次又会比前一次慢一旦在短时间内 Service 被杀死4-5次则系统不再拉起。
4.4 账户同步拉活
手机系统设置里会有“帐户”一项功能任何第三方APP都可以通过此功能将数据在一定时间内同步到服务器中去。系统在将APP帐户同步时会将未启动的APP进程拉活
1开启账户服务
public class AuthenticationService extends Service {private AccountAuthenticator accountAuthenticator;NullableOverridepublic IBinder onBind(Intent intent) {return accountAuthenticator.getIBinder();}Overridepublic void onCreate() {super.onCreate();accountAuthenticator new AccountAuthenticator(this);}static class AccountAuthenticator extends AbstractAccountAuthenticator {public AccountAuthenticator(Context context) {super(context);}Overridepublic Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {return null;}Overridepublic Bundle addAccount(AccountAuthenticatorResponse response, String accountType,String authTokenType, String[] requiredFeatures,Bundle options) throws NetworkErrorException {return null;}Overridepublic Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,Bundle options) throws NetworkErrorException {return null;}Overridepublic Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,String authTokenType, Bundle options) throwsNetworkErrorException {return null;}Overridepublic String getAuthTokenLabel(String authTokenType) {return null;}Overridepublic Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,String authTokenType, Bundle options) throwsNetworkErrorException {return null;}Overridepublic Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,String[] features) throws NetworkErrorException {return null;}}
}
在manifest中配置service service android:name.account.AuthenticationServiceintent-filteraction android:nameandroid.accounts.AccountAuthenticator //intent-filtermeta-dataandroid:nameandroid.accounts.AccountAuthenticatorandroid:resourcexml/authenticator //service在xml中添加authenticator.xml
?xml version1.0 encodingutf-8?
account-authenticator xmlns:androidhttp://schemas.android.com/apk/res/androidandroid:accountTypecom.dn.daemon.accountandroid:iconmipmap/ic_launcherandroid:labelstring/app_name /!--accountType表示账户类型必须唯一--2添加账户
public class AccountHelper {//与authenticator.xml中accountType一致private static final String ACCOUNT_TYPE com.dn.daemon.account;private static final String CONTENT_AUTHORITY com.dn.daemon.provider;public static void addAccount(Context context) {AccountManager accountManager (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);Account[] accounts accountManager.getAccountsByType(ACCOUNT_TYPE);if (accounts.length 0) {//账户已存在return;}Account account new Account(hxl, ACCOUNT_TYPE);accountManager.addAccountExplicitly(account, dn123, new Bundle());//直接添加账户}
}
......3同步服务
创建一个Service作为同步Service并且在onBind返回AbstractThreadedSyncAdapter的getSyncAdapterBinder
public class SyncService extends Service {private static final String TAG SyncService;private SyncAdapter syncAdapter;NullableOverridepublic IBinder onBind(Intent intent) {return syncAdapter.getSyncAdapterBinder();}Overridepublic void onCreate() {super.onCreate();syncAdapter new SyncAdapter(this, true);}static class SyncAdapter extends AbstractThreadedSyncAdapter {public SyncAdapter(Context context, boolean autoInitialize) {super(context, autoInitialize);}Overridepublic void onPerformSync(Account account, Bundle extras, String authority,ContentProviderClient provider, SyncResult syncResult) {Log.e(TAG,账户同步了);}}
}在manifest中配置service service android:name.account.SyncServiceintent-filteraction android:nameandroid.content.SyncAdapter //intent-filtermeta-dataandroid:nameandroid.content.SyncAdapterandroid:resourcexml/syncadapter //service在xml中添加syncadapter.xml
?xml version1.0 encodingutf-8?
sync-adapter xmlns:androidhttp://schemas.android.com/apk/res/androidandroid:contentAuthoritycom.dn.daemon.providerandroid:accountTypecom.dn.daemon.accountandroid:userVisiblefalseandroid:supportsUploadingfalseandroid:allowParallelSyncsfalseandroid:isAlwaysSyncabletrue/!--contentAuthority 系统在进行账户同步的时候会查找 此auth的ContentProvider--!--accountType表示账户类型与authenticator.xml里要一致--!-- userVisible 是否在“设置”中显示--!-- supportsUploading 是否必须notifyChange通知才能同步--!-- allowParallelSyncs 允许多个账户同时同步--!--isAlwaysSyncable 设置所有账号的isSyncable为1--
4创建ContentProvider
public class SyncProvider extends ContentProvider {Overridepublic boolean onCreate() {return false;}NullableOverridepublic Cursor query(NonNull Uri uri, Nullable String[] projection, Nullable String selection,Nullable String[] selectionArgs, Nullable String sortOrder) {return null;}NullableOverridepublic String getType(NonNull Uri uri) {return null;}NullableOverridepublic Uri insert(NonNull Uri uri, Nullable ContentValues values) {return null;}Overridepublic int delete(NonNull Uri uri, Nullable String selection,Nullable String[] selectionArgs) {return 0;}Overridepublic int update(NonNull Uri uri, Nullable ContentValues values, Nullable String selection,Nullable String[] selectionArgs) {return 0;}
}在manifest中配置ContentProvider providerandroid:authoritiescom.dn.daemon.providerandroid:name.account.SyncProviderandroid:exportedfalse/
5开启同步
为了达到进程保活的效果可以开启自动同步。时间间隔虽然设置了1s但是Android本身为了考虑同步所带来的消耗和减少唤醒设备的次数1s只是一个参考时间
public class AccountHelper {//与authenticator.xml中accountType一致private static final String ACCOUNT_TYPE com.dn.daemon.account;private static final String CONTENT_AUTHORITY com.dn.daemon.provider;public static void addAccount(Context context) {AccountManager accountManager (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);Account[] accounts accountManager.getAccountsByType(ACCOUNT_TYPE);if (accounts.length 0) {//账户已存在return;}Account account new Account(hxl, ACCOUNT_TYPE);accountManager.addAccountExplicitly(account, dn123, new Bundle());//直接添加账户}public static void autoSync() {Account dongnao new Account(hxl, ACCOUNT_TYPE);//设置同步ContentResolver.setIsSyncable(dongnao, CONTENT_AUTHORITY, 1);//设置自动同步ContentResolver.setSyncAutomatically(dongnao, CONTENT_AUTHORITY, true);//设置同步周期ContentResolver.addPeriodicSync(dongnao, CONTENT_AUTHORITY, new Bundle(), 1);}
}4.5 JobScheduler拉活
JobScheduler允许在特定状态与特定时间间隔周期执行任务。可以利用它的这个特点完成保活的功能,效果即开启一个定时器与普通定时器不同的是其调度由系统完成。
public class MyJobService extends JobService {private static final String TAG MyJobService;public static void startJob(Context context) {JobScheduler jobScheduler (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);JobInfo.Builder builder new JobInfo.Builder(10,new ComponentName(context.getPackageName(),MyJobService.class.getName())).setPersisted(true);/*** I was having this problem and after review some blogs and the official documentation,* I realised that JobScheduler is having difference behavior on Android N(24 and 25).* JobScheduler works with a minimum periodic of 15 mins.**/if (Build.VERSION.SDK_INT Build.VERSION_CODES.N){//7.0以上延迟1s执行builder.setMinimumLatency(1000);}else{//每隔1s执行一次jobbuilder.setPeriodic(1000);}jobScheduler.schedule(builder.build());}Overridepublic boolean onStartJob(JobParameters jobParameters) {Log.e(TAG,开启job);//7.0以上轮询if (Build.VERSION.SDK_INT Build.VERSION_CODES.N){startJob(this);}return false;}Overridepublic boolean onStopJob(JobParameters jobParameters) {return false;}
}MyJobService.startJob(this);4.6 推送拉活
根据终端不同在小米手机包括 MIUI接入小米推送、华为手机接入华为推送。
4.7 Native拉活
Native fork子进程用于观察当前app主进程的存亡状态。对于5.0以上成功率极低然而目前5.0以下的手机只占10%
4.8 双进程守护
两个进程共同运行如果有其中一个进程被杀那么另外一个进程就会将被杀的进程重新拉起。相对于其他方案成功率比较高。
public class LocalService extends Service {private MyBinder myBinder;class MyBinder extends IMyAidlInterface.Stub{Overridepublic void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString) throws RemoteException {}}NullableOverridepublic IBinder onBind(Intent intent) {return myBinder;}Overridepublic void onCreate() {super.onCreate();myBinder new MyBinder();if (Build.VERSION.SDK_INT Build.VERSION_CODES.O) {NotificationChannel channel new NotificationChannel(deamon, deamon,NotificationManager.IMPORTANCE_LOW);NotificationManager manager (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);if (manager null)return;manager.createNotificationChannel(channel);Notification notification new NotificationCompat.Builder(this,deamon).setAutoCancel(true).setCategory(Notification.CATEGORY_SERVICE).setOngoing(true).setPriority(NotificationManager.IMPORTANCE_LOW).build();startForeground(10, notification);} else if (Build.VERSION.SDK_INT Build.VERSION_CODES.JELLY_BEAN_MR2) {//如果 18 以上的设备 启动一个Service startForeground给相同的id//然后结束那个ServicestartForeground(10, new Notification());startService(new Intent(this, InnnerService.class));} else {startForeground(10, new Notification());}}Overridepublic int onStartCommand(Intent intent, int flags, int startId) {bindService(new Intent(this, RemoteService.class), new MyServiceConnection(),BIND_AUTO_CREATE);return super.onStartCommand(intent, flags, startId);}private class MyServiceConnection implements ServiceConnection {Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {//回调}Overridepublic void onServiceDisconnected(ComponentName componentName) {//startService(new Intent(LocalService.this, RemoteService.class));bindService(new Intent(LocalService.this, RemoteService.class), new MyServiceConnection(),BIND_AUTO_CREATE);}}public static class InnnerService extends Service {Overridepublic void onCreate() {super.onCreate();startForeground(10, new Notification());stopSelf();}NullableOverridepublic IBinder onBind(Intent intent) {return null;}}
}public class RemoteService extends Service {private MyBinder myBinder;class MyBinder extends IMyAidlInterface.Stub {Overridepublic void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString) throws RemoteException {}}NullableOverridepublic IBinder onBind(Intent intent) {return myBinder;}Overridepublic void onCreate() {super.onCreate();myBinder new MyBinder();if (Build.VERSION.SDK_INT Build.VERSION_CODES.O) {NotificationChannel channel new NotificationChannel(deamon, deamon,NotificationManager.IMPORTANCE_LOW);NotificationManager manager (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);if (manager null)return;manager.createNotificationChannel(channel);Notification notification new NotificationCompat.Builder(this,deamon).setAutoCancel(true).setCategory(Notification.CATEGORY_SERVICE).setOngoing(true).setPriority(NotificationManager.IMPORTANCE_LOW).build();startForeground(10, notification);} else if (Build.VERSION.SDK_INT Build.VERSION_CODES.JELLY_BEAN_MR2) {//如果 18 以上的设备 启动一个Service startForeground给相同的id//然后结束那个ServicestartForeground(10, new Notification());startService(new Intent(this, InnnerService.class));} else {startForeground(10, new Notification());}}Overridepublic int onStartCommand(Intent intent, int flags, int startId) {bindService(new Intent(this, LocalService.class), new MyServiceConnection(),BIND_AUTO_CREATE);return super.onStartCommand(intent, flags, startId);}private class MyServiceConnection implements ServiceConnection {Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {}Overridepublic void onServiceDisconnected(ComponentName componentName) {startService(new Intent(RemoteService.this, LocalService.class));bindService(new Intent(RemoteService.this, LocalService.class),new MyServiceConnection(), BIND_AUTO_CREATE);}}public static class InnnerService extends Service {Overridepublic void onCreate() {super.onCreate();startForeground(10, new Notification());stopSelf();}NullableOverridepublic IBinder onBind(Intent intent) {return null;}}
}SuppressLint(NewApi)
public class MyJobService extends JobService {private static final String TAG MyJobService;public static void startJob(Context context) {JobScheduler jobScheduler (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);JobInfo.Builder builder new JobInfo.Builder(10,new ComponentName(context.getPackageName(),MyJobService.class.getName())).setPersisted(true);/*** I was having this problem and after review some blogs and the official documentation,* I realised that JobScheduler is having difference behavior on Android N(24 and 25).* JobScheduler works with a minimum periodic of 15 mins.**/if (Build.VERSION.SDK_INT Build.VERSION_CODES.N) {//7.0以上延迟1s执行builder.setMinimumLatency(1000);} else {//每隔1s执行一次jobbuilder.setPeriodic(1000);}jobScheduler.schedule(builder.build());}Overridepublic boolean onStartJob(JobParameters jobParameters) {Log.e(TAG, 开启job);//7.0以上轮询if (Build.VERSION.SDK_INT Build.VERSION_CODES.N) {startJob(this);}//判断服务是否在运行boolean isLocalServiceRun isServiceRunning(this, LocalService.class.getName());boolean isRemoteServiceRun isServiceRunning(this, RemoteService.class.getName());if (!isLocalServiceRun || !isRemoteServiceRun) {startService(new Intent(this, LocalService.class));startService(new Intent(this, RemoteService.class));}return false;}private boolean isServiceRunning(Context context, String serviceName) {ActivityManager am (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);ListActivityManager.RunningServiceInfo runningServices am.getRunningServices(10);for (ActivityManager.RunningServiceInfo runningService : runningServices) {if (TextUtils.equals(runningService.service.getClassName(), serviceName)) {return true;}}return false;}Overridepublic boolean onStopJob(JobParameters jobParameters) {return false;}
}manifest设置不同进程 service android:name.service.LocalServiceandroid:exportedtrueandroid:process:local/service android:name.service.LocalService$InnnerServiceandroid:exportedtrueandroid:process:local/service android:name.service.RemoteServiceandroid:exportedtrueandroid:process:remote/service android:name.service.RemoteService$InnnerServiceandroid:exportedtrueandroid:process:remote/service android:name.service.MyJobServiceandroid:permissionandroid.permission.BIND_JOB_SERVICE/启动进程 startService(new Intent(this, LocalService.class));startService(new Intent(this, RemoteService.class));MyJobService.startJob(this);最新总结
Android 保活从入门到放弃乖乖引导用户加白名单吧(附7大机型加白示例) 文章转载自: http://www.morning.tpnx.cn.gov.cn.tpnx.cn http://www.morning.fllfc.cn.gov.cn.fllfc.cn http://www.morning.gyfhk.cn.gov.cn.gyfhk.cn http://www.morning.jxlnr.cn.gov.cn.jxlnr.cn http://www.morning.slfmp.cn.gov.cn.slfmp.cn http://www.morning.ngcbd.cn.gov.cn.ngcbd.cn http://www.morning.xsgxp.cn.gov.cn.xsgxp.cn http://www.morning.mzmqg.cn.gov.cn.mzmqg.cn http://www.morning.rrcxs.cn.gov.cn.rrcxs.cn http://www.morning.kchwr.cn.gov.cn.kchwr.cn http://www.morning.hdrsr.cn.gov.cn.hdrsr.cn http://www.morning.qnypp.cn.gov.cn.qnypp.cn http://www.morning.mnrqq.cn.gov.cn.mnrqq.cn http://www.morning.qxmpp.cn.gov.cn.qxmpp.cn http://www.morning.grqlc.cn.gov.cn.grqlc.cn http://www.morning.gblrn.cn.gov.cn.gblrn.cn http://www.morning.tqjks.cn.gov.cn.tqjks.cn http://www.morning.datadragon-auh.cn.gov.cn.datadragon-auh.cn http://www.morning.zwpzy.cn.gov.cn.zwpzy.cn http://www.morning.phlrp.cn.gov.cn.phlrp.cn http://www.morning.rqkk.cn.gov.cn.rqkk.cn http://www.morning.zcnwg.cn.gov.cn.zcnwg.cn http://www.morning.khcpx.cn.gov.cn.khcpx.cn http://www.morning.qwwhs.cn.gov.cn.qwwhs.cn http://www.morning.hcwlq.cn.gov.cn.hcwlq.cn http://www.morning.wcyr.cn.gov.cn.wcyr.cn http://www.morning.qdsmile.cn.gov.cn.qdsmile.cn http://www.morning.tqbyw.cn.gov.cn.tqbyw.cn http://www.morning.prjty.cn.gov.cn.prjty.cn http://www.morning.smj78.cn.gov.cn.smj78.cn http://www.morning.jbctp.cn.gov.cn.jbctp.cn http://www.morning.jkftn.cn.gov.cn.jkftn.cn http://www.morning.kfstq.cn.gov.cn.kfstq.cn http://www.morning.mrbmc.cn.gov.cn.mrbmc.cn http://www.morning.qftzk.cn.gov.cn.qftzk.cn http://www.morning.fwmln.cn.gov.cn.fwmln.cn http://www.morning.nzmw.cn.gov.cn.nzmw.cn http://www.morning.zwwhq.cn.gov.cn.zwwhq.cn http://www.morning.xrksf.cn.gov.cn.xrksf.cn http://www.morning.lbbrw.cn.gov.cn.lbbrw.cn http://www.morning.mrqwy.cn.gov.cn.mrqwy.cn http://www.morning.qzglh.cn.gov.cn.qzglh.cn http://www.morning.zhengdaotang.cn.gov.cn.zhengdaotang.cn http://www.morning.dqdss.cn.gov.cn.dqdss.cn http://www.morning.hbhnh.cn.gov.cn.hbhnh.cn http://www.morning.yrmgh.cn.gov.cn.yrmgh.cn http://www.morning.lmbm.cn.gov.cn.lmbm.cn http://www.morning.jhtrb.cn.gov.cn.jhtrb.cn http://www.morning.chongzhanggui.cn.gov.cn.chongzhanggui.cn http://www.morning.prprj.cn.gov.cn.prprj.cn http://www.morning.thlzt.cn.gov.cn.thlzt.cn http://www.morning.nafdmx.cn.gov.cn.nafdmx.cn http://www.morning.nzwp.cn.gov.cn.nzwp.cn http://www.morning.trplf.cn.gov.cn.trplf.cn http://www.morning.nzmhk.cn.gov.cn.nzmhk.cn http://www.morning.qzmnr.cn.gov.cn.qzmnr.cn http://www.morning.ljcjc.cn.gov.cn.ljcjc.cn http://www.morning.ldzxf.cn.gov.cn.ldzxf.cn http://www.morning.mlnzx.cn.gov.cn.mlnzx.cn http://www.morning.jkdtz.cn.gov.cn.jkdtz.cn http://www.morning.mqfkd.cn.gov.cn.mqfkd.cn http://www.morning.ztcwp.cn.gov.cn.ztcwp.cn http://www.morning.fbfnk.cn.gov.cn.fbfnk.cn http://www.morning.qlkjh.cn.gov.cn.qlkjh.cn http://www.morning.fpjw.cn.gov.cn.fpjw.cn http://www.morning.jhrtq.cn.gov.cn.jhrtq.cn http://www.morning.rflcy.cn.gov.cn.rflcy.cn http://www.morning.lmknf.cn.gov.cn.lmknf.cn http://www.morning.jjhrj.cn.gov.cn.jjhrj.cn http://www.morning.qhqgk.cn.gov.cn.qhqgk.cn http://www.morning.jbkcs.cn.gov.cn.jbkcs.cn http://www.morning.fydsr.cn.gov.cn.fydsr.cn http://www.morning.pjjkz.cn.gov.cn.pjjkz.cn http://www.morning.pqrhb.cn.gov.cn.pqrhb.cn http://www.morning.lmpfk.cn.gov.cn.lmpfk.cn http://www.morning.yfphk.cn.gov.cn.yfphk.cn http://www.morning.qmsbr.cn.gov.cn.qmsbr.cn http://www.morning.mfcbk.cn.gov.cn.mfcbk.cn http://www.morning.tnjff.cn.gov.cn.tnjff.cn http://www.morning.cbynh.cn.gov.cn.cbynh.cn