Android效能優化篇之服務優化
引言
1. Android效能優化篇之記憶體優化--記憶體洩漏
2.Android效能優化篇之記憶體優化--記憶體優化分析工具
3.Android效能優化篇之UI渲染效能優化
4.Android效能優化篇之計算效能優化
5.Android效能優化篇之電量優化(1)——電量消耗分析
6.Android效能優化篇之電量優化(2)
7.Android效能優化篇之網路優化
8.Android效能優化篇之Bitmap優化
9.Android效能優化篇之圖片壓縮優化
10.Android效能優化篇之多執行緒併發優化
11.Android效能優化篇之資料傳輸效率優化
12.Android效能優化篇之程式啟動時間效能優化
13.Android效能優化篇之安裝包效能優化
14.Android效能優化篇之服務優化
介紹
service:是一個後臺服務,專門用來處理常駐後臺的工作的元件。
服務的優化 主要體驗在兩個方面:一·服務的保活,二·服務後臺對於執行任務的集中管理.下面我們主要對服務的保活方面進行講解,至於任務集中管理執行,在電量優化中已經講過,這裡就不再累贅。
開始先來說下我們實現的方式:
1.提高程式優先順序
2.java層雙程式守護
3.1個畫素的Activity保活
4.JobScheduler輪詢
5.native層雙程式守護
今天我們只寫前三種方式,第四種native層雙程式守護將在NDK章節講解。
我們先來看下程式的優先順序 :
1. 前臺程式
- Activity已呼叫onResume()方法
- Service服務已呼叫startForeground()
- 生命週期回撥的Service (onCreate() 、onStart()或onDestroy())
- 正執行其onReceive()方法的BroadcastReceiver
2. 可見程式
- 不在前臺、但仍對使用者可見的Activity(比如呼叫其onPause()方法)
- 繫結到可見(或前臺)Activity 的Service
3. 服務程式
- startService()方法啟動的服務,且不屬於上面兩類
4. 後臺程式
- 對使用者不可見的 Activity 的程式已呼叫 Activity 的onStop()方法
5. 空程式
- 不含任何活動應用元件的程式
下面一起來看看程式在什麼時候會被殺死:
1.應用記憶體不足,回收程式
提高程式優先順序,減少程式oom_adj值,如啟動程式的setForeground()提高程式優先順序
當應用程式退到後臺時,釋放佔用的資源,因為當oom_adj相同時,優先釋放記憶體消耗大的程式
一直在後臺執行的程式一定要輕
2.系統第三方清理軟體,殺死程式
使用aidl,實現雙程式守護
白名單
3.各大rom廠商在應用退出時,會清理殺死程式
使用NDK,輪詢檢視指定程式是否被殺死,如果殺死fork程式,啟動
使用JobScheduler,輪詢檢視指定程式是否被殺死,如果殺死,啟動
雙程式守護(基於java層)
這裡我們將用到aidl,有不瞭解的同學可以自己去了解下,我們先來上程式碼:
1.編寫aidl介面
interface ProcessConnect {
}
介面裡面什麼都沒有,這個只是用來監聽是否斷開連線,如果斷開,就程式碼啟動服務。
2.工作服務
public class MessageService extends Service {
private String TAG = "MessageService";
private int ID=0X00022;
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
Log.e(TAG, "MessageService====>print");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//assert uri
String path = "file:///android_asset/xiaoxin.wav";
Notification.Builder builder = new Notification.Builder(mContext);
Notification notification = builder
.setContentText("messageservice")
.setSmallIcon(R.drawable.ting)
.setSound(Uri.parse(path))
.build();
startForeground(ID,notification);
bindService(new Intent(MessageService.this,GuardService.class),mServiceConnection,BIND_WAIVE_PRIORITY);
return START_STICKY;
}
public ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "MessageService====>onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
startService(new Intent(MessageService.this,GuardService.class));
bindService(new Intent(MessageService.this,GuardService.class),mServiceConnection,BIND_WAIVE_PRIORITY);
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new ProcessConnect.Stub() {
};
}
}
3.守護服務
public class GuardService extends Service {
private Context mContext;
private int ID=0X00021;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//assert uri
String path = "file:///android_asset/xiaoxin.wav";
Notification.Builder builder = new Notification.Builder(mContext);
Notification notification = builder
.setContentText("GuardService")
.setSmallIcon(R.drawable.ting)
.setSound(Uri.parse(path))
.build();
startForeground(ID,notification);
bindService(new Intent(GuardService.this,MessageService.class),mServiceConnection,BIND_WAIVE_PRIORITY);
return START_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new ProcessConnect.Stub(){
};
}
public ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e("GuardService", "GuardService====>onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
startService(new Intent(GuardService.this,MessageService.class));
bindService(new Intent(GuardService.this,MessageService.class),mServiceConnection,BIND_WAIVE_PRIORITY);
}
};
}
從上面兩個服務可以看到,每當一個服務結束,另一個服務就會啟動它,來實現程式不被關閉。
4.MainActivity開啟服務
startService(new Intent(this,MessageService.class));
startService(new Intent(this,GuardService.class));
5.配置
<service android:name=".MessageService"></service>
//新的程式中執行
<service android:name=".GuardService" android:process=":guardservice"></service>
主要五步就搞定了,很簡單吧,但是不要高興的太早,因為這種雙程式守護的方法,只能對4.0以下有效,對於4.0以上機型,只能部分有用,這個問題最後再說,我們先來看下使用JobScheduler,輪詢啟動被殺死的程式。
1個畫素的Activity保活
啟動一個1個畫素的Activity,當使用者解鎖以後將這個Activity結束掉(順便同時把自己的核心服務再開啟一次)。被使用者發現了就不好了。
重點就是對螢幕進行監聽,下面我們來分析程式碼:1個畫素的Activity實現:
Window window = getWindow();
window.setGravity(Gravity.LEFT|Gravity.TOP);
LayoutParams params = window.getAttributes();
params.height = 1;
params.width = 1;
params.x = 0;
params.y = 0;
window.setAttributes(params);
對螢幕進行監聽
private void registerListener() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
mContext.registerReceiver(mScreenReceiver, filter);
}
JobScheduler
在android開發中,會存在這麼些場景 : 你需要在稍後的某個時間點或者當滿足某個特定的條件時執行一個任務,例如當裝置接通電源介面卡或者連線到WIFI。幸運的是在API 21 ( Android 5.0,即Lollipop )中,google提供了一個新叫做JobScheduler API的元件來處理這樣的場景。
當一系列預置的條件被滿足時,JobScheduler API為你的應用執行一個操作。與AlarmManager不同的是這個執行時間是不確定的。除此之外,JobScheduler API允許同時執行多個任務。這允許你的應用執行某些指定的任務時不需要考慮時機控制引起的電池消耗。
下面我們就使用JobScheduler來啟動我們被殺死的服務:
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class JobWakeUpService extends JobService {
private JobScheduler service;
private int JobId=100;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
JobInfo info = new JobInfo.Builder(JobId,new ComponentName(this,JobWakeUpService.class))
.setPeriodic(2000)
.build();
service = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
service.schedule(info);
return START_STICKY;
}
@Override
public boolean onStartJob(JobParameters params) {
Log.e("JobWakeUpService", "JobWakeUpService====>print");
//開始定時任務
if(!isServiceWork(this,MessageService.class.getName())){
//
startService(new Intent(this,MessageService.class));
}
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
//停止
service.cancel(JobId);
// service.cancelAll();
return false;
}
private boolean isServiceWork(Context context,String serviceName){
ActivityManager am= (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> runningServices = am.getRunningServices(100);
if(runningServices == null){
return false;
}
for (ActivityManager.RunningServiceInfo service : runningServices) {
String className = service.service.getClassName();
if(className.equals(serviceName)){
return true;
}
}
return false;
}
}
我們看到這邊就是使用JobScheduler服務來進行迴圈呼叫我們的JobWakeUpService的onStartJob。
我們接下來看下配置:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
<service android:name=".JobWakeUpService"
android:enabled="true"
android:permission="android.permission.BIND_JOB_SERVICE"
></service>
呼叫:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
startService(new Intent(this, JobWakeUpService.class));
}
這個就能實現輪詢檢視指定程式是否被殺死,如果殺死,啟動的功能。
可能你們想問這種方式是否可以解決5.0以上程式不被殺死嗎?我只能遺憾的告訴你,不能,我在華為7.0上的測試,沒有能夠起來。
我們看了這麼多的方式,也不能解決程式不被殺死的情況,那有沒有更好的辦法呢?
native層雙程式守護
關於NDK來實現雙程式守護將在ndk文章中講解。
下載地址:NoDieService-Demo
相關文章
- Android效能優化(1)—webview優化篇Android優化WebView
- 效能優化|Tomcat 服務優化優化Tomcat
- Android效能優化之佈局優化Android優化
- Android 效能優化之記憶體優化Android優化記憶體
- Android效能優化篇之記憶體優化--記憶體洩漏Android優化記憶體
- 六、Android效能優化之UI卡頓分析之渲染效能優化Android優化UI
- Android 效能優化(十二)之我為什麼寫效能優化Android優化
- Android 效能優化 ---- 啟動優化Android優化
- Android效能優化----卡頓優化Android優化
- Linux 效能優化之 cup 篇Linux優化
- Linux 效能優化之 IO 篇Linux優化
- Android效能優化Android優化
- 效能優化篇優化
- iOS效能優化系列篇之“列表流暢度優化”iOS優化
- iOS效能優化系列篇之“優化總體原則”iOS優化
- Android效能優化——圖片優化(二)Android優化
- Linux 效能優化之 CPU 篇 ----- 套路篇Linux優化
- Android效能優——佈局優化Android優化
- Android深度效能優化--記憶體優化(一篇就夠)Android優化記憶體
- Android效能優化——效能優化的難題總結Android優化
- Android效能優化(Memory)Android優化
- IOS效能優化篇iOS優化
- 高效能服務端優化之路服務端優化
- Linux 效能優化之 記憶體 篇Linux優化記憶體
- Android效能優化筆記(一)——啟動優化Android優化筆記
- Android效能優化 筆記Android優化筆記
- 前端效能優化JavaScript篇前端優化JavaScript
- Android效能優化(4):UI渲染機制以及優化Android優化UI
- Linux 效能優化之 CPU 篇 ----- 殭屍程式Linux優化
- 效能優化之資料庫篇2-事務與鎖優化資料庫
- iOS 效能篇一一UITableView效能優化iOSUIView優化
- 【前端效能優化】vue效能優化前端優化Vue
- Android記憶體優化之圖片優化Android記憶體優化
- Android應用優化之冷啟動優化Android優化
- Android效能優化——列表類控制元件卡頓優化Android優化控制元件
- Android效能優化全方面解析Android優化
- Android App效能優化技能,看這篇就夠了AndroidAPP優化
- 效能優化開篇綜述優化