原作者:“裂缝中的阳光dg”,本文由即时通讯网重新修订并整理发布,感谢原作者的无私分享。
20170713111737824.png (51.16 KB, 下载次数: 2392)
下载附件 保存到相册
7 年前 上传
注:优先级1表示最高级,普通进程的oom_adj>=0,系统进程oom_adj<0,系统会根据相应的内存阀值对符合某段oom_adj值的进程进行回收。另外,oom_adj值也会随着占用物理内存越大而增大,系统进程绝对不会被系统杀死。
/**前台Service,使用startForeground * 这个Service尽量要轻,不要占用过多的系统资源,否则 * 系统在资源紧张时,照样会将其杀死 * * Created by jianddongguo on 2017/7/7. */ public class DaemonService extends Service { private static final String TAG = "DaemonService"; public static final int NOTICE_ID = 100; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); if(Contants.DEBUG) Log.d(TAG,"DaemonService---->onCreate被调用,启动前台service"); //如果API大于18,需要弹出一个可见通知 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ Notification.Builder builder = new Notification.Builder(this); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setContentTitle("KeepAppAlive"); builder.setContentText("DaemonService is runing..."); startForeground(NOTICE_ID,builder.build()); // 如果觉得常驻通知栏体验不好 // 可以通过启动CancelNoticeService,将通知移除,oom_adj值不变 Intent intent = new Intent(this,CancelNoticeService.class); startService(intent); }else{ startForeground(NOTICE_ID,new Notification()); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { // 如果Service被终止 // 当资源允许情况下,重启service return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); // 如果Service被杀死,干掉通知 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ NotificationManager mManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); mManager.cancel(NOTICE_ID); } if(Contants.DEBUG) Log.d(TAG,"DaemonService---->onDestroy,前台service被杀死"); // 重启自己 Intent intent = new Intent(getApplicationContext(),DaemonService.class); startService(intent); } }
/** 移除前台Service通知栏标志,这个Service选择性使用 * * Created by jianddongguo on 2017/7/7. */ public class CancelNoticeService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if(Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2){ Notification.Builder builder = new Notification.Builder(this); builder.setSmallIcon(R.mipmap.ic_launcher); startForeground(DaemonService.NOTICE_ID,builder.build()); // 开启一条线程,去移除DaemonService弹出的通知 new Thread(new Runnable() { @Override public void run() { // 延迟1s SystemClock.sleep(1000); // 取消CancelNoticeService的前台 stopForeground(true); // 移除DaemonService弹出的通知 NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); manager.cancel(DaemonService.NOTICE_ID); // 任务完成,终止自己 stopSelf(); } }).start(); } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); } }
<service android:name=".service.DaemonService" android:enabled="true" android:exported="true" android:process=":daemon_service"/> <service android:name=".service.CancelNoticeService" android:enabled="true" android:exported="true" android:process=":service"/>
E:\Android\StudioProject\KeepAppAlive>adb shell shell@trltechn:/ $ su root@trltechn:/ # ps | grep jiangdg
1.png (21.95 KB, 下载次数: 2371)
root@trltechn:/ # cat /proc/15689/oom_adj root@trltechn:/ # cat /proc/16033/oom_adj
2.png (37.62 KB, 下载次数: 2379)
注意:如果执行su命令,提示"/system/bin/sh: su: not found",说明手机设备没有被root。ps命令用于显示静态进程状态,top命令可以对进程进行实时监控,每次启动KeepAppAlive进程号都不一样。
/**1像素管理类 * * Created by jianddongguo on 2017/7/8. */ public class ScreenManager { private static final String TAG = "ScreenManager"; private Context mContext; private static ScreenManager mSreenManager; // 使用弱引用,防止内存泄漏 private WeakReference<Activity> mActivityRef; private ScreenManager(Context mContext){ this.mContext = mContext; } // 单例模式 public static ScreenManager getScreenManagerInstance(Context context){ if(mSreenManager == null){ mSreenManager = new ScreenManager(context); } return mSreenManager; } // 获得SinglePixelActivity的引用 public void setSingleActivity(Activity mActivity){ mActivityRef = new WeakReference<>(mActivity); } // 启动SinglePixelActivity public void startActivity(){ if(Contants.DEBUG) Log.d(TAG,"准备启动SinglePixelActivity..."); Intent intent = new Intent(mContext,SinglePixelActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent); } // 结束SinglePixelActivity public void finishActivity(){ if(Contants.DEBUG) Log.d(TAG,"准备结束SinglePixelActivity..."); if(mActivityRef != null){ Activity mActivity = mActivityRef.get(); if(mActivity != null){ mActivity.finish(); } } } }
A a = new A(); B b = new B(a);
/**1像素Activity * * Created by jianddongguo on 2017/7/8. */ public class SinglePixelActivity extends AppCompatActivity { private static final String TAG = "SinglePixelActivity"; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(Contants.DEBUG) Log.d(TAG,"onCreate--->启动1像素保活"); // 获得activity的Window对象,设置其属性 Window mWindow = getWindow(); mWindow.setGravity(Gravity.LEFT | Gravity.TOP); WindowManager.LayoutParams attrParams = mWindow.getAttributes(); attrParams.x = 0; attrParams.y = 0; attrParams.height = 1; attrParams.width = 1; mWindow.setAttributes(attrParams); // 绑定SinglePixelActivity到ScreenManager ScreenManager.getScreenManagerInstance(this).setSingleActivity(this); } @Override protected void onDestroy() { if(Contants.DEBUG) Log.d(TAG,"onDestroy--->1像素保活被终止"); if(! SystemUtils.isAppAlive(this,Contants.PACKAGE_NAME)){ Intent intentAlive = new Intent(this, SportsActivity.class); intentAlive.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intentAlive); Log.i(TAG,"SinglePixelActivity---->APP被干掉了,我要重启它"); } super.onDestroy(); } }
/** 运动界面,启动监听锁屏广播,判断是否开关1像素界面 * * Created by jianddongguo on 2017/7/7. */ public class SportsActivity extends AppCompatActivity { // 动态注册锁屏等广播 private ScreenReceiverUtil mScreenListener; // 1像素Activity管理类 private ScreenManager mScreenManager; // 代码省略... private ScreenReceiverUtil.SreenStateListener mScreenListenerer = new ScreenReceiverUtil.SreenStateListener() { @Override public void onSreenOn() { // 移除"1像素" mScreenManager.finishActivity(); } @Override public void onSreenOff() { // 接到锁屏广播,将SportsActivity切换到可见模式 // "咕咚"、"乐动力"、"悦动圈"就是这么做滴 // Intent intent = new Intent(SportsActivity.this,SportsActivity.class); // startActivity(intent); // 如果你觉得,直接跳出SportActivity很不爽 // 那么,我们就制造个"1像素"惨案 mScreenManager.startActivity(); } @Override public void onUserPresent() { // 解锁,暂不用,保留 } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sports); if(Contants.DEBUG) Log.d(TAG,"--->onCreate"); // 1. 注册锁屏广播监听器 mScreenListener = new ScreenReceiverUtil(this); mScreenManager = ScreenManager.getScreenManagerInstance(this); mScreenListener.setScreenReceiverListener(mScreenListenerer); } // 代码省略... }
<activity android:name=".SportsActivity" android:launchMode="singleTask"/> <activity android:name=".SinglePixelActivity" android:configChanges="keyboardHidden|orientation|screenSize|navigation|keyboard" android:excludeFromRecents="true" android:finishOnTaskLaunch="false" android:launchMode="singleInstance" android:theme="@style/SingleActivityStyle"/>
<style name="SingleActivityStyle" parent="horizontal_slide"> <!-- 窗体背景颜色为透明 --> <item name="android:windowBackground">@android:color/transparent</item> <!-- 窗体没有边框 --> <item name="android:windowFrame">@null</item> <!-- 窗体不包含标题栏 --> <item name="android:windowNoTitle">true</item> <!-- 窗体悬浮 --> <item name="android:windowIsFloating">true</item> <!-- 自定义TitleBar时去掉多余的阴影--> <item name="android:windowContentOverlay">@null</item> <!-- 不允许窗体背景变暗--> <item name="android:backgroundDimEnabled">false</item> <!-- 窗体切换无动画--> <item name="android:windowAnimationStyle">@null</item> <!-- 禁用窗口的预览动画--> <item name="android:windowDisablePreview">true</item> <item name="android:windowNoDisplay">false</item> </style>
a.png (42.23 KB, 下载次数: 2365)
b.png (40.4 KB, 下载次数: 2426)
c.png (162.02 KB, 下载次数: 2375)
/**循环播放一段无声音频,以提升进程优先级 * * Created by jianddongguo on 2017/7/11. */ public class PlayerMusicService extends Service { private final static String TAG = "PlayerMusicService"; private MediaPlayer mMediaPlayer; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); if(Contants.DEBUG) Log.d(TAG,TAG+"---->onCreate,启动服务"); mMediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.silent); mMediaPlayer.setLooping(true); } @Override public int onStartCommand(Intent intent, int flags, int startId) { new Thread(new Runnable() { @Override public void run() { startPlayMusic(); } }).start(); return START_STICKY; } private void startPlayMusic(){ if(mMediaPlayer != null){ if(Contants.DEBUG) Log.d(TAG,"启动后台播放音乐"); mMediaPlayer.start(); } } private void stopPlayMusic(){ if(mMediaPlayer != null){ if(Contants.DEBUG) Log.d(TAG,"关闭后台播放音乐"); mMediaPlayer.stop(); } } @Override public void onDestroy() { super.onDestroy(); stopPlayMusic(); if(Contants.DEBUG) Log.d(TAG,TAG+"---->onCreate,停止服务"); // 重启 Intent intent = new Intent(getApplicationContext(),PlayerMusicService.class); startService(intent); } }
<service android:name=".service.PlayerMusicService" android:enabled="true" android:exported="true" android:process=":music_service"/>
注:Mate8循环播放一段无声音频,当用户点击一键清理最近应用时,KeepAppAlive不会被干掉,但是如果用户只选择清理KeepAppAlive时,也会被杀死,这与"咕咚"保活效果一致。
d.gif (1023.47 KB, 下载次数: 2402)
e.gif (709.5 KB, 下载次数: 2354)
来源:即时通讯网 - 即时通讯开发者社区!
轻量级开源移动端即时通讯框架。
快速入门 / 性能 / 指南 / 提问
轻量级Web端即时通讯框架。
详细介绍 / 精编源码 / 手册教程
移动端实时音视频框架。
详细介绍 / 性能测试 / 安装体验
基于MobileIMSDK的移动IM系统。
详细介绍 / 产品截图 / 安装体验
一套产品级Web端IM系统。
详细介绍 / 产品截图 / 演示视频
引用此评论
引用:814687491@qq.co 发表于 2018-02-04 19:35 看得出来楼主,在用心的写这篇文章,并且这篇文章也很有价值,但我还是要说一下,在荣耀8上(或者小米系列 ...
引用:jdz612 发表于 2018-01-06 16:10 1像素保活的方法,SinglePixelActivity设置了android:excludeFromRecents="true" ,这样锁屏再截屏后主acti ...
引用:JackJiang 发表于 2018-02-04 19:44 现在Android官方是越来越意识到后台运行的危害:偷跑、耗电等等无限下动作,所以基本上各种保活黑科技越 ...
引用:814687491@qq.co 发表于 2018-02-04 19:57 如果是正规的app,可以让用户设置白名单,进入白名单的app,还是可以使用你分享的这些办法。
引用:bingo2017 发表于 2017-10-20 14:16 非常不错,受益匪浅~
精华主题数超过100个。
连续任职达2年以上的合格正式版主
为论区做出突出贡献的开发者、版主等。
Copyright © 2014-2024 即时通讯网 - 即时通讯开发者社区 / 版本 V4.4
苏州网际时代信息科技有限公司 (苏ICP备16005070号-1)
Processed in 0.187500 second(s), 46 queries , Gzip On.