- 不保留系统launcher
在mk文件中添加这个属性LOCAL_OVERRIDES_PACKAGES := Launcher3 对应的mk中删除,不让其编译即可。
- 保留系统默认的Launcher
当系统存在多个launcher时,若没有设置默认launcher,开机启动后会弹出提示框,罗列所有launcher,用户选择并设置了默认launcher后,按home键以及以后重启都会进入默认的launcher。亦或者在设置--》应用和通知--》默认应用--》主屏幕应用 中也可设置默认launcher。
客户希望系统能直接就进入我设定的launcher而不是弹出框后选择然后设置
前提:客户的app需要有home属性
<intent-filter>
<action android:name="" />
<category android:name=""/>
<category android:name=""/>
<category android:name="" />
</intent-filter>
修改方法:
首先我们需要增加全局属性.DEFAULT_LAUNCHER,,客户可通过修改该属性设置自定义桌面
1:增加自定义属性:
//frameworks\base\core\java\android\provider\
public static final class Global extends NameValueTable {
public static final String DEFAULT_LAUNCHER = "my_default_launcher";
}
public static final class System extends NameValueTable {
public static final String DEFAULT_LAUNCHER = Global.DEFAULT_LAUNCHER;
PUBLIC_SETTINGS.add(DEFAULT_LAUNCHER);
MOVED_TO_GLOBAL.add(.DEFAULT_LAUNCHER);
}
frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\
private void loadGlobalSettings(SQLiteDatabase db) {
loadStringSetting(stmt, .DEFAULT_LAUNCHER,
.default_launcher);
}
//frameworks\base\packages\SettingsProvider\res\values\
<string name="default_launcher" translatable="false">.launcher3/.</string>
两种方法可选:
- 修改弹出框界面直接设置launcher,弹出提示框界面是:frameworks/base/core/java/com/android/internal/app/:修改方法:在configureContentView内直接读取自定义的桌面,然后替代launcher3
1:frameworks/base/core/java/com/android/internal/app/ 的configureContentView 读取设置的默认桌面,进行设置,mResolvingHome就是表示需要选择的是不是home
在这里只针对home作处理。
public boolean configureContentView(List<Intent> payloadIntents, Intent[] initialIntents,
List<ResolveInfo> rList) {
//....
if (rebuildCompleted) {
//....
//phoebe add for default launcher for prop .DEFAULT_LAUNCHER
if(mResolvingHome){
String defaultlauncher = (getContentResolver(), .DEFAULT_LAUNCHER);
final TargetInfo defaultTarget = (defaultlauncher);
(TAG, "zmm add for configureContentView:defaultlauncher:" + defaultlauncher + ":" + defaultTarget);
if (defaultTarget != null) {
safelyStartActivity(defaultTarget);
();
mRegistered = false;
finish();
return true;
}
}
}
}
2:在ResolveListAdapter 增加targetInfoForDefault方法,并且在rebuildList成功以后,再次设置默认laucnher
public class ResolveListAdapter extends BaseAdapter {
@Nullable
public TargetInfo targetInfoForDefault(String info) {
if ((info)) {
return null;
}
///
String[] namesArray = ().split("/");
if (namesArray == null || < 2) {
return null;
}
String packageName = namesArray[0];
String activityInfo = namesArray[1];
if ((packageName) || (activityInfo)) {
return null;
}
ComponentName componentName = new ComponentName((), ());
(TAG, "zmm add for targetInfoForDefault:" + componentName + ":" + ());
for (TargetInfo targetInfo : mDisplayList) {
ComponentName targetComponentName = ();
if ((targetComponentName)) {
return targetInfo;
}
}
return null;
}
private void postListReadyRunnable() {
if (mPostListReadyRunnable == null) {
mPostListReadyRunnable = new Runnable() {
@Override
public void run() {
//phoebe add for default launcher for prop .DEFAULT_LAUNCHER
String defaultlauncher = mResolvingHome ? ((), .DEFAULT_LAUNCHER) : null;
final TargetInfo defaultTarget = (defaultlauncher) ? null : (defaultlauncher);
(TAG, "zmm add for postListReadyRunnable defaultlauncher:" + defaultlauncher + ":" + defaultTarget);
if (defaultTarget != null) {
safelyStartActivity(defaultTarget);
finish();
return;
}
setHeader();
resetButtonBar();
onListRebuilt();
mPostListReadyRunnable = null;
}
};
getMainThreadHandler().post(mPostListReadyRunnable);
}
}
}
修改ActivityManagerService 跳过ResolverActivity
1:ActivityStartController 的startHomeActivity方法内读取用户设置的桌面,并且跳过Settings,和Provision
因为第一次开机,会先Settings的CryptKeeper(加密),FallbackHome(设备正在启动中)接着是provision 的默认桌面,再是launcher3的Launcher页面
zmm add for startHomeActivity...:ComponentInfo{/}
zmm add for startHomeActivity...:ComponentInfo{/}
zmm add for startHomeActivity...:ComponentInfo{/}
zmm add for startHomeActivity....:ComponentInfo{.launcher3/.}
//frameworks/base/services/core/java/com/android/server/wm/
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) {
final ActivityOptions options = ();
(WINDOWING_MODE_FULLSCREEN);
if (!()) {
// The resolver activity shouldn't be put in home stack because when the foreground is
// standard type activity, the resolver activity should be put on the top of current
// foreground instead of bring home stack to front.
(ACTIVITY_TYPE_HOME);
}
//phoebe add for default launcher for prop .DEFAULT_LAUNCHER skip settings,Provision
String shortName = (intent == null || () == null) ? null : ().getPackageName();
if (!isSettingsApp(shortName) && !isProvisionApp(shortName) && setTargetActivityAsPreferredActivity()) {
//(TAG, " zmm add for startHomeActivity as user seetings..");
return;
}
//phoebe add for default launcher for prop .DEFAULT_LAUNCHER skip settings,Provision end
...
}
//判断是不是Settings app
private boolean isSettingsApp(String shortName) {
return shortName != null && ("");
}
//判断是不是Provision app
private boolean isProvisionApp(String shortName) {
return shortName != null && ("");
}
//设置用户设置的桌面
private boolean setTargetActivityAsPreferredActivity() {
boolean result = false;
Context context = ;
if (context == null)
return result;
String info = ((), .DEFAULT_LAUNCHER);
(TAG, " zmm add for setTargetActivityAsPreferredActivity info=" + info);
if ((info)) {
return result;
}
String[] namesArray = ("/");
if (namesArray == null || < 2) {
return result;
}
String packageName = namesArray[0];
String activityInfo = namesArray[1];
if ((packageName) || (activityInfo)) {
return result;
}
IntentFilter filter = new IntentFilter();
("");
("");
("");
Intent intent = new Intent(Intent.ACTION_MAIN);
(Intent.CATEGORY_HOME);
packageName = ();
activityInfo = ();
PackageManager pm = ();
List<ResolveInfo> list = (intent, 0);
final int N = list == null ? 0 : ();
ComponentName[] set = new ComponentName[N];
ComponentName componentName = null;
int bestMatch = 0;
for (int i = 0; i < N; i++) {
ResolveInfo r = (i);
set[i] = new ComponentName(, );
if ( > bestMatch) bestMatch = ;
if (() && ()) { /*modify target apk packageName 填写你的包名*/
componentName = set[i];
}
}
// (TAG, "zmm add for setTargetActivityAsPreferredActivity newcomponentName=" + componentName);
if (null != componentName) {
(filter, IntentFilter.MATCH_CATEGORY_EMPTY, set, componentName);
(Intent.FLAG_ACTIVITY_NEW_TASK);
(intent);
result = true;
}
return result;
}
2:接着修改frameworks/base/services/core/java/com/android/server/pm/,需要把用户在设置--》默认应用中选择的桌面应用保存到自定义的属性中。
ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
int userId) {
...
for (int i = 0; i < resolveInfosSize; i++) {
ResolveInfo resolveInfo = (i);
if ( != null && (
, packageName)) {
//phoebe add start
ComponentName componentName = new ComponentName(,
);
(TAG, "zmm add for getHomeActivitiesAsUser:com:"+componentName);
String value = + "/" + ;
((),
.DEFAULT_LAUNCHER, value);
//phoebe add end
return componentName;
}
}
return null;
}
以上两种都可实现根据用户配置切换默认launcher
1:adb 切换
adb shell settings put global my_default_launcher .launcher3/.
2:app可如此调用:
(getContentResolver(), "my_default_launcher", "/");
客户的app如果是普通的三方app,设置Global属性可能是报错没有权限:
(getContentResolver(), "my_default_launcher", "/");
报错:缺少权限:.WRITE_SECURE_SETTINGS
该权限是系统app才能申请的权限,普通app申请不到的话,我们可以去掉该限制。
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/
@@ -1249,18 +1250,23 @@ public class SettingsProvider extends ContentProvider {
private boolean mutateGlobalSetting(String name, String value, String tag,
boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
int mode) {
- // Make sure the caller can change the settings - treated as secure.
- enforceWritePermission(.WRITE_SECURE_SETTINGS);
String pkg = ""; //数据写入时使用系统settings应用的包名,系统会进行调用进程的包名判断
if(!"my_default_launcher".equals(name)){ //phoebe add 自定义数据不进行权限验证
pkg = "";
// Make sure the caller can change the settings - treated as secure.
enforceWritePermission(.WRITE_SECURE_SETTINGS);
}
//下面修改在插入操作时使用上面预设的包名,绕过包名验证
@@ -1268,7 +1274,7 @@ public class SettingsProvider extends ContentProvider {
case MUTATION_OPERATION_INSERT: {
return (SETTINGS_TYPE_GLOBAL,
UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
- getCallingPackage(), forceNotify, CRITICAL_GLOBAL_SETTINGS);
+ "".equals(pkg)?getCallingPackage():pkg, forceNotify, CRITICAL_GLOBAL_SETTINGS);
}
每日语录:滴水穿石!!!加油!!!
单曲循环《如愿》