您的位置:首页 > 移动开发 > Android开发

android 应用自启管理

2017-12-19 18:03 471 查看
因项目的需要,做一个自启管理的功能,管理其它app的自启动。看到这个功能的时候我有点无从下手,大多数第三方的管理app是没有这个功能的,网上关于这个功能的例子也很少,没有什么好的参考。只能自己研究了。很多的app的自启都是靠监听系统的广播,像最典型的就是开机广播。所以我想到的方法是禁止应用收听相关的广播来实现。有一个方法可以禁止掉android四大组件的使用。

public void setComponentEnabledSetting (ComponentName componentName, int newState, int flags)
componentName:组件名称
newState:组件新的状态,可以设置三个值,分别是如下:
不可用状态:COMPONENT_ENABLED_STATE_DISABLED
可用状态:COMPONENT_ENABLED_STATE_ENABLED
默认状态:COMPONENT_ENABLED_STATE_DEFAULT
flags:行为标签,值可以是DONT_KILL_APP或者0。 0说明杀死包含该组件的app
public int getComponentEnabledSetting(ComponentName componentName)
获取组件的状态


特别注意setComponentEnabledSetting 这个方法是需要系统权限的,也就是说用这个方法去实现必须可以拿到系统权限。

下面说下具体的实现,首先获取到需要禁止掉应用的信息,数据保存在ArrayList里面。AutoStartInfo用来

存储信息。

public static List<AutoStartInfo> fetchAutoApps(Context mContext) {
PackageManager pm = mContext.getPackageManager();
Intent[] intents=getIntents();
List<AutoStartInfo> appList = new ArrayList<AutoStartInfo>();
String appName = null;
Drawable icon = null;
String packageName =null;
boolean isSystem = false;
boolean isenable = true;
List<ResolveInfo> resolveInfoList=null;
for (Intent intent : intents) {
resolveInfoList = pm.queryBroadcastReceivers(intent, PackageManager.MATCH_DISABLED_COMPONENTS);
for (int i = 0; i < resolveInfoList.size(); i++) {
AutoStartInfo mAutoStartInfo = new AutoStartInfo();
Log.d(TAG, "appName "+appName+" packageName "+packageName);
mAutoStartInfo.setLabel(appName);
mAutoStartInfo.setSystem(isSystem);
mAutoStartInfo.setEnable(isenable);
mAutoStartInfo.setIcon(icon);
mAutoStartInfo.setPackageName(packageName);
if(isAdd(appList,packageName)&&packageName!=null){
appList.add(mAutoStartInfo);
}
appName = resolveInfoList.get(i).loadLabel(pm).toString();
packageName = resolveInfoList.get(i).activityInfo.packageName;
// Log.d(TAG, "packageName 1 " + packageName + " packageReceiver " + packageReceiver);
icon = resolveInfoList.get(i).loadIcon(pm);
ComponentName mComponentName2 = new ComponentName(resolveInfoList.get(i).activityInfo.packageName, resolveInfoList.get(i).activityInfo.name);
if (pm.getComponentEnabledSetting(mComponentName2) == 2) {
isenable = false;
} else {
isenable = true;
}
if ((resolveInfoList.get(i).activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
isSystem = true;
} else {
isSystem = false;
}
}
}
return appList;
}


intents里面包含了所要禁止的广播种类,这里我禁止了5种广播。

public static Intent[] getIntents(){
return new Intent[]{
new Intent("android.intent.action.BATTERY_CHANGED"),new Intent("android.intent.action.BOOT_COMPLETED"),new Intent("android.net.conn.CONNECTIVITY_CHANGE"),new Intent("android.intent.action.LOCALE_CHANGED"),
new Intent("android.intent.action.USER_PRESENT")
};
}


这里的isAdd()方法用来限制添加相同的包名,因为有些应用可能注册了这里的几个广播。

private static Boolean isAdd(List<AutoStartInfo> list, String packageName){
for (AutoStartInfo autoStartInfo : list) {
if (packageName.equals(autoStartInfo.getPackageName())) {
Log.d("appListadd", "getPackageName " + autoStartInfo.getPackageName() + " packageName " + packageName);
return false;
}
}
return true;
}


AutoStartInfo.java类保存信息

public class AutoStartInfo {
private String label;
private String packageName;
private Drawable icon;
private String name;

private String packageReceiver;
private String desc;
/**  是否是系统进程. */
public boolean isSystem;
public boolean isenable;

public String getLabel() {
return label;
}

public void setLabel(String label) {
this.label = label;
}

public String getPackageName() {
return packageName;
}

public void setPackageName(String packageName) {
this.packageName = packageName;
}

public String getDesc() {
return desc;
}

public void setDesc(String desc) {
this.desc = desc;
}

public Drawable getIcon() {
return icon;
}

public void setIcon(Drawable icon) {
this.icon = icon;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public boolean isSystem() {
return isSystem;
}

public void setSystem(boolean isSystem) {
this.isSystem = isSystem;
}

public boolean isEnable() {
return isenable;
}

public void setEnable(boolean enable) {
this.isenable = enable;
}

public String getPackageReceiver() {
return packageReceiver;
}

public void setPackageReceiver(String packageReceiver) {
this.packageReceiver = packageReceiver;
}
}


布局的话比较简单,一个ListView,ListView的item里面放一个Switch来控制开关,这里就不贴代码了。

在Adapater里面实现相关逻辑。

holder.disable_switch.setOnCheckedChangeListener(null);
Log.i(TAG, " item.getPackageName() "+item.getPackageName()+"getView Boolean= " + getSharedPreferences(mContext,item.getPackageName(),false));
if (getSharedPreferences(mContext,item.getPackageName(),false)) {
holder.disable_switch.setChecked(true);
} else {
holder.disable_switch.setChecked(false);
}

holder.disable_switch.setOnCheckedChangeListener(new SwitchButtonChangeListener(item.getPackageName()));


这里本来是很简单的代码,但是我在使用的时候一直有问题,把switch的开关打开,然后滑动listView,开关又自动关闭了。在网上有人解决了,就是加上holder.disable_switch.setOnCheckedChangeListener(null)这句。

这里我使用SharedPreferences来保存数据,用包名来当key.

private void operateSharedPreferences(Context context,String packageName,Boolean value){
SharedPreferences preferences=context.getSharedPreferences("user",Context.MODE_PRIVATE);
SharedPreferences.Editor editor=preferences.edit();
editor.putBoolean(packageName,value);
editor.commit();
}

private Boolean getSharedPreferences(Context context,String packageName,Boolean value){
SharedPreferences preferences=context.getSharedPreferences("user", Context.MODE_PRIVATE);
boolean bool=preferences.getBoolean(packageName, value);
return bool;
}


SwitchButtonChangeListener的实现,把packageName传进去

private class SwitchButtonChangeListener implements CompoundButton.OnCheckedChangeListener {
private String mPackageName ;
SwitchButtonChangeListener(String packageName){
mPackageName= packageName;
}

@Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
diasableApp(mPackageName,isChecked);
}
}


最核心的方法diasableApp(),里面包含了数据的存储和是否接受相关的广播

private void diasableApp(String packageName,Boolean isDiasableApp) {
Intent[] intents=BootStartUtils.getIntents();
List<String> listReceiver = BootStartUtils.addReceiver(intents, mContext.getPackageManager(), packageName);
controlBroadcastReceiver(mContext,packageName,listReceiver,isDiasableApp);
notifyDataSetChanged();
operateSharedPreferences(mContext,packageName,isDiasableApp);
}


private void  controlBroadcastReceiver(Context context,String packageName,List<String> broadcastReceiverName,boolean isStop){
PackageManager pm=context.getPackageManager();
for (String s : broadcastReceiverName) {
ComponentName componentName = new ComponentName(packageName, s);
if (isStop == true){
//禁止接收相关的广播            pm.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);
}else {
//允许接收相关的广播    pm.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP);
}
}
}


到此,这个功能就基本上实现了,附上一张效果图。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: