Android 11--设置第三方Launcher并默认 与 如何预置apk
1.0Ver
/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
+ private void setDefaultLauncher() {
+ try {
+ final PackageManager pm = getPackageManager();
+
+ //String defPackageName = "com.android.launcher3";
+ String defPackageName = "com.demo.launcher3";
+ String defClassName;
+
+ //defClassName = "com.android.searchlauncher.SearchLauncher";
+ defClassName = "com.demo.launcher.MainActivity";
+
+ Log.i("deflauncher", "deflauncher : PackageName = " +
+ defPackageName + " ClassName = " + defClassName);
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction("android.intent.action.MAIN");
+ filter.addCategory("android.intent.category.HOME");
+ filter.addCategory("android.intent.category.DEFAULT");
+
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+ List<ResolveInfo> list = new ArrayList<ResolveInfo>();
+ list = pm.queryIntentActivities(intent, 0);
+ final int N = list.size();
+ ComponentName[] set = new ComponentName[N];
+ int bestMatch = 0;
+ for (int i = 0; i < N; i++) {
+ ResolveInfo r = list.get(i);
+ set[i] = new ComponentName(r.activityInfo.packageName,
+ r.activityInfo.name);
+ if (r.match > bestMatch) bestMatch = r.match;
+ }
+ ComponentName preActivity = new ComponentName(defPackageName, defClassName);
+ pm.addPreferredActivity(filter, bestMatch, set, preActivity);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
protected void onCreate(Bundle savedInstanceState, Intent intent,
CharSequence title, int defaultTitleRes, Intent[] initialIntents,
List<ResolveInfo> rList, boolean supportsAlwaysUseOption) {
setTheme(appliedThemeResId());
super.onCreate(savedInstanceState);
+ if(mResolvingHome){
+ setDefaultLauncher();
+ finish();
+ return;
+ }
+
...
2.0Ver
/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
public final void onPostListReady(ResolverListAdapter listAdapter, boolean doPostProcessing,
boolean rebuildCompleted) {
...
if (isAutolaunching()) {
return;
}
+ //add start
+ if(setCustomerDefLauncher()){
+ return;
+ }
+ //add end
...
}
final boolean postRebuildListInternal(boolean rebuildCompleted) {
//...
//add start
if (rebuildCompleted && (setCustomerDefLauncher() || maybeAutolaunchActivity())) {
return true;
}
//add end
}
//add start
+ private boolean setCustomerDefLauncher(){
+ String defLauncher = "com.demo.launcher3";
+ int size = mMultiProfilePagerAdapter.getActiveListAdapter().getDisplayResolveInfoCount();
+ android.util.Log.d("TAG","setCustomerDefLauncher:"+size);
+ for (int i = 0; i<size; i++){
+ DisplayResolveInfo dInfo = mMultiProfilePagerAdapter.getActiveListAdapter().getDisplayResolveInfo(i);
+ if (null != dInfo && defLauncher.equals(dInfo.getResolveInfo().activityInfo.packageName)) {
+ Log.d("TAG", "find need set default launcher, set default launcher--->" + dInfo.getResolveInfo().activityInfo. packageName);
+ startSelected(i, true, false);
+ return true;
+ }
+ }
+ return false;
+ }
//add end
多个launcher时,防止闪屏
/frameworks/base/core/java/com/android/internal/app/ResolverListAdapter.java;
protected boolean rebuildList(boolean doPostProcessing) {
...
//add start
+ String defLauncher = "com.demo.launcher3;
+ for (ResolvedComponentInfo info : currentResolveList) {
+ ResolveInfo resolveInfo = info.getResolveInfoAt(0);
+ if (defLauncher.equals(resolveInfo.activityInfo.packageName)) {
+ currentResolveList = new ArrayList<>();
+ currentResolveList.add(info);
+ Log.d("tww", "find set default launcher--->" + resolveInfo.activityInfo.packageName);
+ break;
+ }
+ }
+ //add end
+
...
}
如果当前为Launcher3显示,然后从设置里面切换默认为第三方Launcher应用,在第三方应用中,点击导航栏返回按键时,会返回到Launcher3,是因为切换设置默认launcher后,前一个的任务栈还存在,需要删除
+import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
+import android.os.RemoteException;
+ private void clearOldLauncherTask() {
+ ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ List<ActivityManager.RunningTaskInfo> list = activityManager.getRunningTasks(Integer.MAX_VALUE);
+ if (list != null) {
+ for (ActivityManager.RunningTaskInfo item : list) {
+ Log.d("tag", "--->" + item.configuration.windowConfiguration.getActivityType());
+ Log.d("tag", "--->" + item.realActivity.getPackageName());
+ //if(item.configuration.windowConfiguration.getActivityType() == WindowConfiguration.ACTIVITY_TYPE_HOME){}
+ if (item.realActivity.getPackageName().equals("com.android.launcher3")) {
+ final int tId = item.taskId;
+ try {
+ Log.d("tag", "tId--->" + tId);
+ ActivityTaskManager.getService().removeTask(tId);
+ } catch (RemoteException e) {
+ Log.d("tag", "--->RemoteException");
+ }
+ }
+ }
+ }
+ }
+
知道了怎么删除旧的Launcher 任务栈,还需要知道删除旧的Launcher任务栈Timing,
第一个Timing点,可以发送广播通知删除旧的
/packages/apps/PermissionController/src/com/android/permissioncontroller/role/model/HomeRoleBehavior.java
@Override
public void onHolderSelectedAsUser(@NonNull Role role, @NonNull String packageName,
@NonNull UserHandle user, @NonNull Context context) {
// Launch the new home app so the change is immediately visible even if the home button is
// not pressed.
Intent intent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
//add start
Intent launcherIntent = new Intent("xxxx.x.x.x.action");
launcherIntent.putExtra("launcher_package_name", packageName);
context.sendBroadcast(launcherIntent);
//add end
}
第二个Timing点
frameworks/base/services/core/java/com/android/server/role/RoleManagerService.java
@Override
public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
@NonNull RemoteCallback callback) {
if (!mUserManagerInternal.exists(userId)) {
Slog.e(LOG_TAG, "user " + userId + " does not exist");
return;
}
userId = handleIncomingUser(userId, false, "addRoleHolderAsUser");
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"addRoleHolderAsUser");
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
Objects.requireNonNull(callback, "callback cannot be null");
getOrCreateController(userId).onAddRoleHolder(roleName, packageName, flags,
callback);
//add start
if (roleName.equals("android.app.role.HOME")) {
Log.i("tag", "change value->packageName:" + packageName);
if (packageName.equals("com.android.launcher3")) {
SystemProperties.set("persist.sys.xxx", null);
} else {
SystemProperties.set("persist.sys.xxx", packageName);
}
//发送广播
}
//add end
}
第二个timing 早于第一个
参考1
3.0Ver 利用role结合2.0Ver删除旧Launcher栈
--- a/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
+++ b/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
@@ -55,6 +55,7 @@ import android.os.IBinder;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.StrictMode;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.MediaStore;
@@ -1040,6 +1041,11 @@ public class ResolverActivity extends Activity implements
if (isAutolaunching()) {
return;
}
+ //add Change to the customer's default launcher xxxx xxxx
+ if(rebuildCompleted && hasCustomerDefLauncher()){
+ return;
+ }
+ //add Change to the customer's default launcher xxxx xxxx
if (isIntentPicker()) {
((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
.setUseLayoutWithDefault(useLayoutWithDefault());
@@ -1061,6 +1067,23 @@ public class ResolverActivity extends Activity implements
}
}
+ //add Change to the customer's default launcher xxxx xxxx
+ private boolean hasCustomerDefLauncher() {
+ String def_customer_launcher = SystemProperties.get("persist.sys.def_customer_launcher", null);
+ if (def_customer_launcher != null && !"".equals(def_customer_launcher)) {
+ int size = mMultiProfilePagerAdapter.getActiveListAdapter().getDisplayResolveInfoCount();
+ for (int i = 0; i < size; i++) {
+ DisplayResolveInfo info = mMultiProfilePagerAdapter.getActiveListAdapter().getDisplayResolveInfo(i);
+ if (info != null && def_customer_launcher.equals(info.getResolveInfo().activityInfo.packageName)) {
+ startSelected(i, true, false);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ //add Change to the customer's default launcher xxxx xxxx
+
protected void onListRebuilt(ResolverListAdapter listAdapter) {
final ItemClickListener listener = new ItemClickListener();
setupAdapterListView((ListView) mMultiProfilePagerAdapter.getActiveAdapterView(), listener);
diff --git a/frameworks/base/core/java/com/android/internal/app/ResolverListAdapter.java b/frameworks/base/core/java/com/android/internal/app/ResolverListAdapter.java
old mode 100644
new mode 100755
index eef722e32b..006e8c00d1
--- a/frameworks/base/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/frameworks/base/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -38,6 +38,7 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
@@ -219,6 +220,22 @@ public class ResolverListAdapter extends BaseAdapter {
}
}
+ //add Resolve pop-up flashing when multiple launchers exist xxxx xxxx
+ if (currentResolveList != null) {
+ String def_customer_launcher = SystemProperties.get("persist.sys.def_customer_launcher", null);
+ if (def_customer_launcher != null && !"".equals(def_customer_launcher)) {
+ for (ResolvedComponentInfo info : currentResolveList) {
+ ResolveInfo resolveInfo = info.getResolveInfoAt(0);
+ if (def_customer_launcher.equals(resolveInfo.activityInfo.packageName)) {
+ currentResolveList = new ArrayList<>();
+ currentResolveList.add(info);
+ break;
+ }
+ }
+ }
+ }
+ //add Resolve pop-up flashing when multiple launchers exist xxxx xxxx
+
// So far we only support a single other profile at a time.
// The first one we see gets special treatment.
for (ResolvedComponentInfo info : currentResolveList) {
diff --git a/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java b/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 0c1bb79279..73f9204ce1 100755
--- a/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -230,6 +230,10 @@ import java.io.PrintWriter;
import java.util.HashSet;
import java.util.List;
+import android.app.role.RoleManager;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
/**
* WindowManagerPolicy implementation for the Android phone UI. This
* introduces a new method suffix, Lp, for an internal lock of the
@@ -5005,7 +5009,33 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
+ setDefaultLauncherItem(mContext);//add
+ }
+
+ //add Whether default selected customer's launcher xxxx xxxx
+ public void setDefaultLauncherItem(Context context) {
+ boolean whether_force = SystemProperties.getBoolean("persist.sys.force_customer_launcher_enable", false);// ture: force use customer's launcher
+ if (!whether_force) return;
+ String packageName = SystemProperties.get("persist.sys.def_customer_launcher", null);
+ if (packageName != null && !"".equals(packageName)) {
+ String roleName = "android.app.role.HOME";
+ boolean add = true;
+ int flags = 0;
+ UserHandle user = Process.myUserHandle();
+ Log.d("PhoneWindowManager_Launcher", "role: " + roleName + ", package: " + packageName);
+ RoleManager roleManager = context.getSystemService(RoleManager.class);
+ Executor executor = context.getMainExecutor();
+ Consumer<Boolean> callback = successful -> {
+ if (successful) {
+ Log.d("PhoneWindowManager_Launcher", "Success , role: " + roleName + ", package: " + packageName);
+ } else {
+ Log.d("PhoneWindowManager_Launcher", "Failed , role: " + roleName + ", package: " + packageName);
+ }
+ };
+ roleManager.addRoleHolderAsUser(roleName, packageName, flags, user, executor, callback);
+ }
}
+ //add Whether default selected customer's launcher xxxx xxxx
/** {@inheritDoc} */
@Override
diff --git a/frameworks/base/services/core/java/com/android/server/role/RoleManagerService.java b/frameworks/base/services/core/java/com/android/server/role/RoleManagerService.java
old mode 100644
new mode 100755
index b75bce833e..24801c396d
--- a/frameworks/base/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/frameworks/base/services/core/java/com/android/server/role/RoleManagerService.java
@@ -48,11 +48,13 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.Log;
import android.util.PackageUtils;
import android.util.Slog;
import android.util.SparseArray;
@@ -515,6 +517,16 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
getOrCreateController(userId).onAddRoleHolder(roleName, packageName, flags,
callback);
+ //add change use launcher xxxx xxxx
+ if (roleName.equals("android.app.role.HOME")) {
+ Log.i("PhoneWindowManager_Launcher", "change persist.sys.def_customer_launcher value->packageName:" + packageName);
+ if (packageName.equals("com.android.launcher3")) {
+ SystemProperties.set("persist.sys.def_customer_launcher", null);
+ } else {
+ SystemProperties.set("persist.sys.def_customer_launcher", packageName);
+ }
+ }
+ //add change use launcher xxxx xxxx
}
@Override
diff --git a/packages/apps/PermissionController/src/com/android/permissioncontroller/role/ui/ManageRoleHolderStateLiveData.java b/packages/apps/PermissionController/src/com/android/permissioncontroller/role/ui/ManageRoleHolderStateLiveData.java
old mode 100644
new mode 100755
index 07698fbc67..0ef9ab6055
--- a/packages/apps/PermissionController/src/com/android/permissioncontroller/role/ui/ManageRoleHolderStateLiveData.java
+++ b/packages/apps/PermissionController/src/com/android/permissioncontroller/role/ui/ManageRoleHolderStateLiveData.java
@@ -19,6 +19,7 @@ package com.android.permissioncontroller.role.ui;
import android.app.role.RoleManager;
import android.content.Context;
import android.os.UserHandle;
+import android.os.SystemProperties;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -74,6 +75,13 @@ public class ManageRoleHolderStateLiveData extends LiveData<Integer> {
Log.i(LOG_TAG, (add ? "Adding" : "Removing") + " package as role holder, role: "
+ roleName + ", package: " + packageName);
}
+ //add force use customer's launcher xxxx xxxx
+ boolean whether_force = SystemProperties.getBoolean("persist.sys.force_customer_launcher_enable", false);// ture: force use customer's launcher
+ if (roleName.equals("android.app.role.HOME") && whether_force){
+ Log.i("PhoneWindowManager_Launcher", "force use customer's launcher,don't change !");
+ return;
+ }
+ //add force use customer's launcher xxxx xxxx
mLastPackageName = packageName;
mLastAdd = add;
mLastFlags = flags;
Android预置Apk,Android.mk/Android.bp
预置apk,整个东西其实非常简单,因为系统本身它自己也内置不少apk,找到对应目录,查看它怎么写,.mk或.bp文件,依葫芦画瓢就行了!!!
系统应用:Browser2,Calendar等,一般都在packages目录下
build/make/target/product/handheld_product.mk
# /product packages
PRODUCT_PACKAGES += \
+ demo \
Browser2 \
Calendar \
Camera2 \
...
Android.bp
android_app_import {
name: "demo", //要编译生成apk名字,单编译模块时候 make MyApp
// this needs to be a privileged application
privileged: true, //当一个模块被标识为 privileged: true 时,它将被视为具有特权权限,
//可以访问系统级别的资源或执行特权操作。
// Make sure the build system doesn't try to resign the APK
dex_preopt: {
enabled: true, // 是否启用dex预优化 是否预先生成dex文件,默认为true。
// 该属性会影响应用的首次启动速度及Android系统的启动速度
},
arch: { //通过cpu平台类型选择apk
arm: {
apk: "demo.apk",
},
arm64: {
apk: "demo.apk",
},
x86: {
apk: "demo.apk",
},
x86_64: {
apk: "demo.apk",
},
},
certificate: "platform", // 指定APK的签名方式
}
//类似
android_app_import {
name: "SogouInput",
apk: "SogouInput.apk",
// 保留apk自己的签名
// presigned: true,
// 打开将放到对应分区目录的priv-app文件夹下
privileged: true,
// 使用系统签名
certificate: "platform",
// 打开将放到system_ext分区
// system_ext_specific: true,
// 打开将放到product分区
// product_specific: true,
// 打开将放到vendor分区
// proprietary: true,
// device_specific: true
dex_preopt: {
enabled: false,
},
}
Android 13 内置三方应用app zzh
可能遇到的问题,预置apk 有没有需要带so库,预置的整个apk是可以卸载还是不能卸载?
//权限问题
frameworks/base/data/etc/privapp-permissions-platform.xml
//Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := MyExample
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_PREBUILT_JNI_LIBS := lib\arm64-v8a\xxxx.so
LOCAL_CERTIFICATE := PRESIGNED
include $(BUILD_PREBUILT)
Android预置第三方Apk,so库不能读取问题
预置无源码apk到Android系统(带so文件)
Android.mk参数解析
添加第三方应用apk文件
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := xxx.apk
LOCAL_MODULE_CLASS := APPS
#可以为user、eng、tests、optional,optional代表在任何版本下都编译
LOCAL_MODULE_TAGS := optional
#编译模块的名称
LOCAL_MODULE := Taobao
#可以为testkey、platform、shared、media、PRESIGNED(使用原签名),platform代表为系统应用
LOCAL_CERTIFICATE := testkey
#应用输出路径,此处为data/app
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
#module的后缀,可不设置
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_DEX_PREOPT := false #不进行预先优化,一般第三方应用会避免优化,而导致APP各种异常
include $(BUILD_PREBUILT)