场景:设备开机后,播放收音机或音乐,如果这个时候关机,或直接拔电重启,则下次启动设备后,恢复播放收音机或音乐,如果启动前音乐在前台,则还需要把音乐恢复到前台,如果启动前是后台,则还是后台播放
思路:
1、音频策略记录在三种状态中记录其当前播放音频的包名和状态,四种状态为:PLAY【记录其播放】、KILL【记录其清楚】、STOP【记录其清除】,通过广播的方式,告知状态管理服务,使其更新SharedPreferences存储的属性mediaPkgName,这个只能告知其是否播放在重启之前,怎么判断当前多媒体音频应用是否在前台,请看第2项
2、通过记录其activity的状态,两种状态Resume和finish,来告知当前启动的应用的包名和下一个应用启动的包名,其实现在activity的管理类ActivityManagerService中
void reportResumedActivityLocked(ActivityRecord r) {
......
int i = mWatchers.beginBroadcast();
while (i > 0) {
i--;
IActivityWatcher w = mWatchers.getBroadcastItem(i);
if (w != null) {
try {
w.activityResuming(identHash);
Intent intent = r.intent;
w.activityOnResume(r.packageName, r.info.name, intent);
if(intent.getCategories() != null || "com.app.package.name".equals(r.info.name)) {
w.topActivityResuming(r.packageName, r.info.name, intent);
}
} catch (RemoteException e) {
}
}
}
mWatchers.finishBroadcast();
}
public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
......
int i = mWatchers.beginBroadcast();
while (i > 0) {
i--;
IActivityWatcher w = mWatchers.getBroadcastItem(i);
if ( w != null) {
try {
Intent intent = next.intent;
w.activityGoingBack(next.packageName, next.info.name, intent);
} catch (RemoteException e) {
}
}
}
mWatchers.finishBroadcast();
......
}
其中,需要明白其activity的服务管理类的watcher的使用,需要你在你的状态服务类里面去注册其watcher,当然不再使用的时候别忘了unregisterActivityWatcher
ActivityManagerService.java
public void registerActivityWatcher(IActivityWatcher watcher) {
synchronized (this) {
mWatchers.register(watcher);
}
}
public void unregisterActivityWatcher(IActivityWatcher watcher) {
synchronized (this) {
mWatchers.unregister(watcher);
}
}
StateManagerService.java
ActivityManagerService.registerActivityWatcher(mWatcher);
此mWatcher是aidl的一个实现类需需要你去实现其相应的接口方法,主要用到下面两个函数
public void activityOnResume(String pkgName, String activityName, Intent intent){
}
public void activityGoingBack(String pkgName, String activityName, Intent intent) {
}
通过上面两个回调函数里面的参数pkgName来判断当前是否为音乐或收音机来记录其状态到SharedPreferences中,下次重启后,再取了看下,最后一次的包名是否为音乐或收音机的,如果是则进行启动该多媒体应用
3、音乐应用里面很多模块,比如SD卡音乐、网络音乐、我的收藏、等等,那么恢复到具体哪个模块,就需要音乐应用自己去记录其最后一次状态了,而这个状态是在其一进去该模块就进行记录的,不能等拔电再记录,那样已经迟了根本不给你记录的机会了
4、我们还需要判断用户是否之前做过恢复出厂设置,当然需要考虑的细节不仅仅这么些,这个需要考虑的细节才是真正的重点,比如我们需要考虑下面一种更可怕的情况,即,如果我们状态保持在开机后需要去启动应用,比如音乐应用,进入到具体某个模块,这个时候可能我们的音频策略服务还没有启动起来,或我们的界面SurfaceFlinger服务也没有起来,而状态保持我们需要直接开机进入那个应用,所以状态服务在system server启动各种服务的时候启动它,这个时候就需要你考虑先后依赖来考虑服务启动顺序
IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
if (surfaceFlinger != null) {
Log.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
Parcel data = Parcel.obtain();
data.writeInterfaceToken("android.ui.ISurfaceComposer");
surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
data, null, 0);
data.recycle();
bCallEnableScreenFlag = true;
}
你还要甚至保证已经是你需要的横屏?
setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false,
mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
上面基本上已经说明了其流程概要,在项目开发中,你会发现不少小细节,行了,就说到这吧,也希望有学习的兄弟能提出更好的方案