Android程序守護,讓APP在系統記憶體中常駐(二)
昨天晚上寫了用系統服務等方法來實現應用保活。今天寫一下用提高app的程序等級來實現應用保活。想看直接呼叫系統方法保活應用的可以點選Android程序守護,讓APP在系統記憶體中常駐(一)進行跳轉。
一:第一種實現思路,建立廣播接收者來監聽系統關屏亮屏操作。當手機關屏時,顯示一個透明的一畫素的activity,此時使用者時看不見的;當手機亮屏時,把這個activity給finish掉。好了,有了思路就開始實現吧。
1.首先新建一個廣播接收者:來判斷當前的螢幕狀態來進行一些操作。
public class AppBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())){ AppReciver.getInstance().startApp(context); }else { AppReciver.getInstance().finishApp(); } } }
2.建立一個1畫素的activity。
@SuppressLint("RtlHardcoded") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_null); //設定1畫素 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); //用來給單例傳過去activity,能讓它finish掉。 AppReciver.getInstance().setActivity(this); }
3.為這個活動建立一個空的透明的主題。
<style name="KeepLive" parent="AppTheme">
<item name="windowBackground">@null</item>
<item name="android:windowIsTranslucent">true</item>
</style>
4.為這個活動修改AndroidManifest中的內容,把它單獨放入一個棧中。讓他使用剛剛為他建立的主題。
<activity android:name=".NullActivity" android:launchMode="singleInstance" android:theme="@style/KeepLive"/>
5.建立一個單例,用來完成開始和結束活動任務的邏輯操作。
class AppReciver {
private static final AppReciver ourInstance = new AppReciver();
private WeakReference<NullActivity> weakReference;
private AppReciver() {
}
static AppReciver getInstance() {
return ourInstance;
}
public void startApp(Context context) {
context.startActivity(new Intent(context, NullActivity.class));
}
public void registerReceiver(Context context) {
AppBroadcastReceiver appBroadcastReceiver = new AppBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.SCREEN_OFF");
intentFilter.addAction("android.intent.action.SCREEN_ON");
intentFilter.addAction("android.intent.action.USER_PRESENT");
context.registerReceiver(appBroadcastReceiver, intentFilter);
}
public void finishApp() {
if (weakReference != null && weakReference.get() != null) {
weakReference.get().finish();
}
}
public void setActivity(NullActivity activity) {
weakReference = new WeakReference(activity);
}
}
6.注意上面的單例中使用了WeakReference來儲存activity。這裡為了避免記憶體洩漏使用了弱引用。最後在活動中呼叫一下就完成了。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1.系統拉活service程序
//startService(new Intent(this,StickService.class));
//2.通過jobScheduler拉活
//startJob();
//3.通過bindService,通過ServiceConnection來拉活
//bindService();
//4.通過activity來提升app的程序等級
AppReciver.getInstance().registerReceiver(this);
}
二:service提升app的程序等級
1.首先新建一個服務。
public class ForegroundService extends Service {
private static final int SERVICE_ID = 1;
public ForegroundService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
2.如果是安卓4.0以下可以直接構建一個空的通知。安卓8.0以上,通知需要設定channel ,還需要設定通知的重要級別 ,安卓9.0以上,通知會直接顯示出來。所以要進行版本的判斷,來實現通知的設定方式。4.0以下的可以直接通過下面一行程式碼呼叫。
if (Build.VERSION.SDK_INT < 18) {
//安卓4.0以下可以直接構建一個空的通知。
//設定成前臺服務,並且去除通知欄訊息
startForeground(SERVICE_ID,new Notification());
}
3.安卓8.0以下的就需要先設定成前臺服務,然後再去通過新的服務去除通知欄的訊息。好了,廢話不說,直接上程式碼。
else if (Build.VERSION.SDK_INT < 26) {
//設定成前臺服務
startForeground(SERVICE_ID,new Notification());
//並且去除通知欄訊息
startService(new Intent(this,InnerService.class));
}
4.InnerService直接寫一個內部服務就行。在裡面進行去除通知欄的訊息。
private class InnerService extends Service{
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(SERVICE_ID,new Notification());
stopForeground(true);
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
}
5.下面是這個服務的完整程式碼。
public class ForegroundService extends Service {
private static final int SERVICE_ID = 1;
public ForegroundService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Build.VERSION.SDK_INT < 18) {
//安卓4.0以下可以直接構建一個空的通知。
//設定成前臺服務,並且去除通知欄訊息
startForeground(SERVICE_ID,new Notification());
} else if (Build.VERSION.SDK_INT < 26) {
//設定成前臺服務
startForeground(SERVICE_ID,new Notification());
//並且去除通知欄訊息
startService(new Intent(this,InnerService.class));
} else {
//安卓8.0以上,通知需要設定channel
//還需要設定通知的重要級別
//安卓9.0以上,通知會直接顯示出來。
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (manager!=null){
NotificationChannel channel = new NotificationChannel("channel","xxx",NotificationManager.IMPORTANCE_NONE);
manager.createNotificationChannel(channel);
Notification notification = new NotificationCompat.Builder(this,"channel").build();
startForeground(SERVICE_ID,notification);
}
}
return super.onStartCommand(intent, flags, startId);
}
private class InnerService extends Service{
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(SERVICE_ID,new Notification());
stopForeground(true);
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
}
}
6.在活動中啟動一下就大功告成了。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1.系統拉活service程序
//startService(new Intent(this,StickService.class));
//2.通過jobScheduler拉活
//startJob();
//3.通過bindService,通過ServiceConnection來拉活
//bindService();
//4.通過activity來提升app的程序等級
//AppReciver.getInstance().registerReceiver(this);
//5.通過Service來提升app的程序等級
startService(new Intent(this,ForegroundService.class));
}
好了,就說到這吧,有什麼補充的或者哪裡說的不對的歡迎在下面評論,一期交流,相互學習。