Android11.0自定义服务中添加设置第三方应用为默认Launcher接口供第三方开发使用
Android11.0自定义服务中添加设置第三方应用为默认Launcher接口供第三方开发使用
本文描述Android11自定义服务中添加设置第三方app为系统默认Launcher接口,提供第三方应用开发使用,如何添加自定义服务:Android11.0Frameworks中添加一个自定义系统服务,并提供jar包供应用开发调用。
- ITestManager及TestManager中添加方法定义,修改文件路径:
/frameworks/base/core/com/yjz/test/api/ITestManager.aidl
boolean hasDefaultLauncher();
int setDefaultLauncher(String packageName);
void clearDefaultLauncher();
/frameworks/base/core/com/yjz/test/TestManager.java
public boolean hasDefaultLauncher() {
try {
return mService.hasDefaultLauncher();
} catch (RemoteException e) {
e.printStackTrace();
}
return false;
}
public int setDefaultLauncher(String packageName) {
try {
return mService.setDefaultLauncher(packageName);
} catch (RemoteException e) {
e.printStackTrace();
}
return 1;
}
public void clearDefaultLauncher() {
try {
mService.clearDefaultLauncher();
} catch (RemoteException e) {
e.printStackTrace();
}
}
- TestManagerService中添加方法,修改路径:
/frameworks/base/services/core/java/com/android/server/yjz/TestManagerService.java;
//*******省略代码******
@Override
public boolean hasDefaultLauncher() throws RemoteException {
return LauncherHelper.getInstance().hasDefaultLauncher();
}
@Override
public int setDefaultLauncher(String s) throws RemoteException {
int result = LauncherHelper.getInstance().checkCanSetDefaultLauncher(mContext, s);
if (result != LauncherHelper.LAUNCHER_SUCCESS) {
return result;
}
final LauncherData data = new LauncherData(new CompletableFuture<>(), s);
Message msg = Message.obtain();
msg.what = MSG_WHAT_SET_LAUNCHER;
msg.obj = data;
mHandler.sendMessage(msg);
try {
boolean success = data.getFuture().get();
Log.d(TAG, "set def launcher result " + success);
return success ? LauncherHelper.LAUNCHER_SUCCESS : LauncherHelper.LAUNCHER_FAIL;
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return LauncherHelper.LAUNCHER_FAIL;
}
@Override
public void clearDefaultLauncher() throws RemoteException {
mHandler.sendEmptyMessage(MSG_WHAT_CLEAR_LAUNCHER);
}
private static final int MSG_WHAT_SET_LAUNCHER = 7;
private static final int MSG_WHAT_CLEAR_LAUNCHER = 8;
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@Override
public void dispatchMessage(@NonNull Message msg) {
switch (msg.what) {
case MSG_WHAT_SET_LAUNCHER:
final LauncherData data = (LauncherData) msg.obj;
LauncherHelper.getInstance().setDefaultLauncher(mContext, data.getPackageName(), isOk -> {
if (isOk) {
clearOldLauncherTask(mContext, data.getPackageName());
}
data.getFuture().complete(isOk);
});
break;
case MSG_WHAT_CLEAR_LAUNCHER:
LauncherHelper.getInstance().clearDefaultLauncher(mContext);
break;
}
}
};
private void clearOldLauncherTask(Context context, String packageName) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> list = manager.getRunningTasks(Integer.MAX_VALUE);
if (null != list) {
for (ActivityManager.RunningTaskInfo item : list) {
if (item.configuration.windowConfiguration.getActivityType() == WindowConfiguration.ACTIVITY_TYPE_HOME) {
if (!item.realActivity.getPackageName().equals(packageName)) {
Log.d(TAG, "clearOldLauncherTask " + item.realActivity.getPackageName());
final int tId = item.taskId;
try {
ActivityTaskManager.getService().removeTask(tId);
} catch (RemoteException e) {
Log.w(TAG, "Failed to remove task=" + tId, e);
}
}
}
}
}
}
private class LauncherData {
private CompletableFuture<Boolean> future;
private String packageName;
public LauncherData(@NonNull CompletableFuture<Boolean> future, @NonNull String packageName) {
this.future = future;
this.packageName = packageName;
}
public CompletableFuture<Boolean> getFuture() {
return future;
}
public String getPackageName() {
return packageName;
}
}
/frameworks/base/core/com/yjz/test/core/LauncherHelper.java
package com.yjz.test.core;
import android.app.role.RoleManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.Log;
import android.util.Singleton;
import com.yjz.test.utils.Tools;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
public class LauncherHelper {
private static final String TAG = "LauncherHelper";
public static final int LAUNCHER_SUCCESS = 0;
public static final int LAUNCHER_FAIL = 1;
public static final int SET_LAUNCHER_ERROR_NOT_FOUND = 2;
public static final int SET_LAUNCHER_ERROR_NOT_HOME = 3;
private final String defLauncherKey = "persist.sys.def_launcher";
private final String defLauncherEnableKey = "persist.sys.def_launcher_enable";
private final byte[] mLock = new byte[0];
private LauncherHelper() {
}
private static final Singleton<LauncherHelper> mSingletonLauncherHelper = new Singleton<LauncherHelper>() {
@Override
protected LauncherHelper create() {
return new LauncherHelper();
}
};
public static LauncherHelper getInstance() {
return mSingletonLauncherHelper.get();
}
public boolean hasDefaultLauncher() {
synchronized (mLock) {
String launcherPackageName = SystemProperties.get(defLauncherKey);
return null != launcherPackageName && !"".equals(launcherPackageName);
}
}
public int checkCanSetDefaultLauncher(Context context, String packageName) {
//检查应用是否已安装
if (null == Tools.getApplicationInfo(context, packageName)) {
return SET_LAUNCHER_ERROR_NOT_FOUND;
}
//检查应用是否是home
if (!isHomeApp(context, packageName)) {
return SET_LAUNCHER_ERROR_NOT_HOME;
}
return LAUNCHER_SUCCESS;
}
public void setDefaultLauncher(Context context, String packageName, SetHomeRoleCallback listener) {
setHomePreferredActivity(context, packageName, true, isOk -> {
if (isOk) {
synchronized (mLock) {
SystemProperties.set(defLauncherKey, packageName);
SystemProperties.set(defLauncherEnableKey, "true");
}
//检查应用是否为前台应用
if (!Tools.isPackageInForeground(context, packageName)) {
Log.d(TAG, "need startup launcher app " + packageName);
Intent intent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivityAsUser(intent, UserHandle.SYSTEM);
}
}
if (null != listener) {
listener.onResult(isOk);
}
});
}
public void clearDefaultLauncher(Context context) {
synchronized (mLock) {
String launcherPackageName = SystemProperties.get(defLauncherKey);
if (null != launcherPackageName && !"".equals(launcherPackageName)) {
PackageManager pm = context.getPackageManager();
pm.clearPackagePreferredActivities(launcherPackageName);
setHomePreferredActivity(context, launcherPackageName, false, null);
}
SystemProperties.set(defLauncherKey, "");
SystemProperties.set(defLauncherEnableKey, "false");
}
}
private boolean isHomeApp(Context context, String packageName) {
PackageManager pm = context.getPackageManager();
Intent queryIntent = new Intent();
queryIntent.addCategory(Intent.CATEGORY_HOME);
queryIntent.setAction(Intent.ACTION_MAIN);
List<ResolveInfo> homeActivities = pm.queryIntentActivities(queryIntent, 0);
if (homeActivities == null) {
return false;
}
for (ResolveInfo info : homeActivities) {
if (info.activityInfo.packageName.equals(packageName)) {
return true;
}
}
return false;
}
private void setHomePreferredActivity(Context context, String packageName, boolean add, SetHomeRoleCallback listener) {
RoleManager roleManager = (RoleManager) context.getSystemService(RoleManager.class);
Executor executor = context.getMainExecutor();
Consumer<Boolean> callback = successful -> {
if (successful) {
Log.i(TAG, "Package " + (add ? "added" : "removed")
+ " as role holder, role: " + RoleManager.ROLE_HOME + ", package: " + packageName);
} else {
Log.i(TAG, "Failed to " + (add ? "add" : "remove")
+ " package as role holder, role: " + RoleManager.ROLE_HOME + ", package: "
+ packageName);
}
if (null != listener) {
listener.onResult(successful);
}
};
if (add) {
roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, packageName, 0, UserHandle.SYSTEM, executor, callback);
} else {
roleManager.removeRoleHolderAsUser(RoleManager.ROLE_HOME, packageName, 0, UserHandle.SYSTEM, executor,
callback);
}
}
public interface SetHomeRoleCallback {
void onResult(boolean isOk);
}
}
/frameworks/base/core/com/yjz/test/utils/Tools.java
public final class Tools {
private static final String TAG = "Tools";
public static ApplicationInfo getApplicationInfo(Context context, String packageName) {
ApplicationInfo info = null;
try {
info = context.getPackageManager().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return null;
}
return info;
}
public static boolean isPackageInForeground(Context context, String packageName){
int uid;
try {
uid = context.getPackageManager().getPackageUid(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
return am.getUidImportance(uid) == IMPORTANCE_FOREGROUND;
}
}
- 提供第三方开发的jar包中添加方法,修改路径 /vendor/yjz/com/yjz/sdk/SDKManager.java;
public boolean hasDefaultLauncher() {
return mTestManager.hasDefaultLauncher();
}
public int setDefaultLauncher(String packageName) {
return mTestManager.setDefaultLauncher(packageName);
}
public void clearDefaultLauncher() {
mTestManager.clearDefaultLauncher();
}
- 编译刷机验证,RoleManager设置的数据中保存在/data/misc_de/0/apexdata/com.android.permission/roles.xml中: