Android 自用 App保活——音樂播放保活適配8.0 (賊好用)
又是好久沒有積累東西了。慚愧,慚愧。。。手動哭泣。閒話說到這裡,下面我介紹一種新的 App 保活方式哈,目前用小米家族手機 涵蓋 Android 5.0 到 Android 8.1家族的測試。結論是,不主動幹掉,是死不了的。但是主動幹掉了,是活不了的。
之前介紹介紹了 雙程序保活,我還大言不慚的 適配 8.0 。但是,從 Android 6.0 之後這個方法及其不好用,說死就死,華為,小米 分分鐘 弄死筆者的 App 。 而且 最噁心的事情,居然 ANR 。 筆者對現在那些閉著眼睛 抄部落格 的大佬實在不敢恭維了。對了,之前的筆記地址為:自己用到的Android 雙服務保活(適配8.0)
一、保活原理
1、準備一首無聲音樂(文末我會提供);
2、在認為可以進行保活的位置 進行啟用服務 播放(筆者在MainActivity 內啟動 服務);
3、在服務的 onCreate()方法內 初始化 MediaPlayer 物件;
4、將 onBind()方法返回值置空;
5、在 onStartCommand()方法內 開啟執行緒 進行音樂播放(筆者選擇播放 3s 之後進行了音樂暫停處理,放置部分 定製 os 出現鎖屏 執行緒音樂播放介面,及其噁心,比如 miui);
6、在 onDestroy( ) 方法內進行關閉 播放器物件,移除播放器物件,重啟本服務。
二、保活程式碼
/** * Content:後臺播放音樂達到保活目的 * Actor:韓小呆 ヾ(✿゚▽゚)ノ * Time: 2018/10/12 10:47 * Update: * Time: */ public class SingASongService extends Service { private MediaPlayer mMediaPlayer; private Thread thread; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); MyThread myThread = new MyThread(); thread = new Thread(myThread); mMediaPlayer = MediaPlayer.create(MainApplication.getInstance(), R.raw.no_kill); mMediaPlayer.setLooping(true); LogUtils.d("onCreate() 建立播放物件:" + mMediaPlayer.hashCode()); } @Override public int onStartCommand(Intent intent, int flags, int startId) { thread.start(); LogUtils.d("播放時 執行緒名稱:" + thread.getName()); return START_STICKY; } //開始、暫停播放 private void startPlaySong() { if (mMediaPlayer == null) { mMediaPlayer = MediaPlayer.create(MainApplication.getInstance(), R.raw.no_kill); LogUtils.d("音樂啟動播放,播放物件為: " + mMediaPlayer.hashCode()); mMediaPlayer.start(); } else { mMediaPlayer.start(); LogUtils.d("音樂啟動播放,播放物件為: " + mMediaPlayer.hashCode()); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } if (mMediaPlayer != null) { mMediaPlayer.pause(); LogUtils.d("音樂啟動播放,播放物件為: " + mMediaPlayer.hashCode()); int progress = mMediaPlayer.getCurrentPosition(); LogUtils.d("音樂暫停,播放進度:" + progress); } } @Override public void onDestroy() { super.onDestroy(); mMediaPlayer.pause(); LogUtils.d("恢復播放 時當前播放器物件:" + mMediaPlayer.hashCode()); stopPlaySong(); LogUtils.d("應用播放服務被殺死,正在重啟"); LogUtils.d("目標播放工作執行緒是否存活:" + thread.isAlive()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(new Intent(getApplicationContext(), SingASongService.class)); } else { startService(new Intent(getApplicationContext(), SingASongService.class)); } } //停止播放銷燬物件 private void stopPlaySong() { if (mMediaPlayer != null) { mMediaPlayer.stop(); LogUtils.d("音樂停止播放,播放物件為:" + mMediaPlayer.hashCode()); LogUtils.d("音樂播放器是否在迴圈:" + mMediaPlayer.isLooping()); LogUtils.d("音樂播放器是否還在播放:" + mMediaPlayer.isPlaying()); mMediaPlayer.release(); LogUtils.d("播放物件銷燬,播放物件為:" + mMediaPlayer.hashCode()); mMediaPlayer = null; } } class MyThread implements Runnable { @Override public void run() { startPlaySong(); } } }
為了方便判定 物件是否被消失,列印日誌有點多,也方便,各位朋友驗證。別 oom 啊。部分程式碼可以進行優化,比如說建立執行緒的方式,我只是為了方便驗證吧,畢竟比較菜。
三、直接使用程式碼
public class SingASongService extends Service {
private MediaPlayer mMediaPlayer;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mMediaPlayer = MediaPlayer.create(MainApplication.getInstance(), R.raw.no_kill);
mMediaPlayer.setLooping(true);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
startPlaySong();
}
}).start();
return START_STICKY;
}
//開始、暫停播放
private void startPlaySong() {
if (mMediaPlayer == null) {
mMediaPlayer = MediaPlayer.create(MainApplication.getInstance(), R.raw.no_kill);
mMediaPlayer.start();
} else {
mMediaPlayer.start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (mMediaPlayer != null) {
mMediaPlayer.pause();
}
}
@Override
public void onDestroy() {
super.onDestroy();
mMediaPlayer.pause();
stopPlaySong();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(new Intent(getApplicationContext(), SingASongService.class));
} else {
startService(new Intent(getApplicationContext(), SingASongService.class));
}
}
//停止播放銷燬物件
private void stopPlaySong() {
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
}
最後提醒部分小白,service 是需要註冊的哦!ヾ(✿゚▽゚)ノ
最最後,給我讀者有什麼 特別的想法 可以隨時 留言 提問。 還有,各位,可以點下小心心,或者是 加個關注啥的‧★,::‧( ̄▽ ̄)/‧:‧°★*