Skip to content

Commit

Permalink
export/restore permissions configs
Browse files Browse the repository at this point in the history
  • Loading branch information
8enet committed May 8, 2017
1 parent ff32d24 commit 387edaf
Show file tree
Hide file tree
Showing 36 changed files with 1,614 additions and 55 deletions.
9 changes: 6 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ apply plugin: 'com.android.application'

android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
buildToolsVersion "25.0.3"
defaultConfig {
applicationId "com.zzzmode.appopsx"
minSdkVersion 19
targetSdkVersion 25
versionCode 113
versionName "1.1.3"
versionCode 115
versionName "1.1.5"
signingConfig signingConfigs.debug
resConfigs "en","zh"
vectorDrawables.useSupportLibrary = true
}

aaptOptions {
Expand All @@ -35,6 +37,7 @@ dependencies {
compile "com.android.support:recyclerview-v7:$supportVersion"
compile "com.android.support:preference-v7:$supportVersion"
compile "com.android.support:preference-v14:$supportVersion"
compile "com.android.support:design:$supportVersion"
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.github.promeg:tinypinyin:2.0.3'
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<activity android:name=".ui.main.SettingsActivity" android:theme="@style/SettingsTheme" android:configChanges="keyboardHidden|orientation"/>
<activity android:name=".ui.main.PermissionGroupActivity" android:configChanges="keyboardHidden|orientation"/>
<activity android:name=".ui.permission.AlertInstalledPremActivity" android:theme="@style/alert.perm"/>
<activity android:name=".ui.main.backup.BackupActivity"/>

<receiver android:name=".ui.core.AppInstalledRevicer" android:enabled="true">
<intent-filter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class AEvent {
public static final String C_SEARCH_APP="search_app";
public static final String C_SETTINGS="main_setting";
public static final String C_PERMISSION_LIST="main_perm_list";
public static final String C_BACKUP="main_backup";
public static final String C_PERM_ITEM="perm_detail_item";
public static final String C_SETTING_AUTO_IGNORE="setting_auto_ignore";
public static final String C_SETTING_IGNORE_TEMPLETE="setting_ignore_templete";
Expand All @@ -31,4 +32,11 @@ public class AEvent {
public static final String C_GROUP_OPEN_ALL="group_open_all";

public static final String U_AUTO_IGNORE="auto_ignore";

public static final String A_EXPORT="perm_export";
public static final String A_DELETE_BACKFILE="delete_back_file";
public static final String A_RESTORE="perm_restore";

public static final String A_DELETE_CONFIRM="delete_back_confirm";
public static final String A_RESTORE_CONFIRM="restore_confirm";
}
152 changes: 120 additions & 32 deletions app/src/main/java/com/zzzmode/appopsx/ui/core/Helper.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,16 @@
import com.zzzmode.appopsx.ui.model.OpEntryInfo;
import com.zzzmode.appopsx.ui.model.PermissionChildItem;
import com.zzzmode.appopsx.ui.model.PermissionGroup;
import com.zzzmode.appopsx.ui.model.PreAppInfo;
import com.zzzmode.appopsx.ui.permission.AppPermissionActivity;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
Expand All @@ -59,8 +62,10 @@
import io.reactivex.SingleEmitter;
import io.reactivex.SingleOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.BiConsumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Function3;
import io.reactivex.functions.Predicate;
import io.reactivex.internal.operators.single.SingleJust;
import io.reactivex.observers.ResourceSingleObserver;
Expand Down Expand Up @@ -339,6 +344,7 @@ public AppInfo apply(String s) throws Exception {
}

public static Observable<List<AppInfo>> getInstalledApps(final Context context, final boolean loadSysapp) {

return Observable.create(new ObservableOnSubscribe<List<AppInfo>>() {
@Override
public void subscribe(final ObservableEmitter<List<AppInfo>> e) throws Exception {
Expand Down Expand Up @@ -400,48 +406,62 @@ public int compare(AppInfo o1, AppInfo o2) {
e.onNext(ret);
e.onComplete();
}
}).map(new Function<List<AppInfo>, List<AppInfo>>() {
});
}


public static Observable<PreAppInfo> getAppsPermission(final Context context, AppInfo[] appInfos){
return Observable.fromArray(appInfos).map(new Function<AppInfo, PreAppInfo>() {
@Override
public List<AppInfo> apply(List<AppInfo> appInfos) throws Exception {
int type = PreferenceManager.getDefaultSharedPreferences(context).getInt("pref_app_sort_type", 0);
Comparator<AppInfo> comparator = null;
if (type == 0) {
//按名称排序
} else if (type == 2) {
//按安装时间排序
comparator = new Comparator<AppInfo>() {
@Override
public int compare(AppInfo o1, AppInfo o2) {
if (o2.installTime == o1.installTime) {
return 0;
public PreAppInfo apply(@NonNull AppInfo s) throws Exception {
OpsResult opsForPackage = AppOpsx.getInstance(context).getOpsForPackage(s.packageName);
if (opsForPackage != null) {
if (opsForPackage.getException() != null) {
throw new Exception(opsForPackage.getException());
}
}else {
throw new NullPointerException("getOpsForPackage:"+s+" return null !");
}
PreAppInfo appInfo=new PreAppInfo(s.packageName);
List<PackageOps> opses = opsForPackage.getList();
if (opses != null) {
StringBuilder sb=new StringBuilder();
for (PackageOps opse : opses) {
List<OpEntry> ops = opse.getOps();

if (ops != null) {
for (OpEntry op : ops) {
if(op.getMode() == AppOpsManager.MODE_IGNORED){
sb.append(op.getOp()).append(',');
}
}
return o2.installTime > o1.installTime ? 1 : -1;
}
};
} else if (type == 3) {
//按最后更新时间排序
comparator = new Comparator<AppInfo>() {
@Override
public int compare(AppInfo o1, AppInfo o2) {
return Math.max(o2.installTime, o2.updateTime) > Math.max(o1.installTime, o1.updateTime) ? 1 : -1;
}
};
}

if (comparator != null) {
Collections.sort(appInfos, comparator);
}
int len=sb.length();
if(len > 0 && sb.charAt(len-1) == ','){
sb.deleteCharAt(len-1);
}
appInfo.setIgnoredOps(sb.toString());
return appInfo;
}else {
throw new NullPointerException("");
}


return appInfos;
}
});
})
.retry(5, new Predicate<Throwable>() {
@Override
public boolean test(Throwable throwable) throws Exception {
return throwable instanceof IOException || throwable instanceof NullPointerException;
}
})
.subscribeOn(Schedulers.io());
}

public static Observable<List<OpEntryInfo>> getAppPermission(final Context context, final String packageName) {
return getAppPermission(context, packageName, false);
}


public static Observable<List<OpEntryInfo>> getAppPermission(final Context context, final String packageName, final boolean needNoPermsOp) {
return Observable.create(new ObservableOnSubscribe<OpsResult>() {
@Override
Expand Down Expand Up @@ -604,7 +624,7 @@ private static OpEntryInfo opEntry2Info(OpEntry op, Context context, PackageMana
}

public static Single<List<PermissionGroup>> getPermissionGroup(final Context context, final boolean loadSysapp) {
return getInstalledApps(context, loadSysapp).concatMap(new Function<List<AppInfo>, ObservableSource<AppInfo>>() {
return getInstalledApps(context, loadSysapp).map(getSortComparator(context)).concatMap(new Function<List<AppInfo>, ObservableSource<AppInfo>>() {
@Override
public ObservableSource<AppInfo> apply(List<AppInfo> appInfos) throws Exception {
return Observable.fromIterable(appInfos);
Expand Down Expand Up @@ -765,6 +785,7 @@ private static List<PermissionGroup> reSort(String[] groupNames, Map<String, Lis
}

public static Observable<OpsResult> setMode(final Context context, final String pkgName, final OpEntryInfo opEntryInfo) {

return Observable.create(new ObservableOnSubscribe<OpsResult>() {
@Override
public void subscribe(ObservableEmitter<OpsResult> e) throws Exception {
Expand All @@ -789,6 +810,34 @@ public boolean test(Throwable throwable) throws Exception {
}


public static Observable<OpsResult> setModes(final Context context, final String pkgName,final int opMode,List<Integer> ops){
return Observable.fromIterable(ops).flatMap(new Function<Integer, ObservableSource<OpsResult>>() {
@Override
public ObservableSource<OpsResult> apply(@NonNull Integer integer) throws Exception {
return Observable.just(integer).map(new Function<Integer, OpsResult>() {
@Override
public OpsResult apply(@NonNull Integer integer) throws Exception {
OpsResult opsForPackage = AppOpsx.getInstance(context).setOpsMode(pkgName, integer, opMode);
if (opsForPackage != null) {
if (opsForPackage.getException() == null) {
return opsForPackage;
} else {
throw new Exception(opsForPackage.getException());
}
}
return null;
}
}).retry(5, new Predicate<Throwable>() {
@Override
public boolean test(Throwable throwable) throws Exception {
return throwable instanceof IOException || throwable instanceof NullPointerException;
}
});
}
});
}


public static Single<SparseIntArray> autoDisable(final Context context, String pkg) {

return SingleJust.just(pkg).map(new Function<String, SparseIntArray>() {
Expand Down Expand Up @@ -986,4 +1035,43 @@ public void subscribe(SingleEmitter<Boolean> e) throws Exception {
});
}

public static Function<List<AppInfo>, List<AppInfo>> getSortComparator(final Context context){
return new Function<List<AppInfo>, List<AppInfo>>() {
@Override
public List<AppInfo> apply(List<AppInfo> appInfos) throws Exception {
int type = PreferenceManager.getDefaultSharedPreferences(context).getInt("pref_app_sort_type", 0);
Comparator<AppInfo> comparator = null;
if (type == 0) {
//按名称排序
} else if (type == 2) {
//按安装时间排序
comparator = new Comparator<AppInfo>() {
@Override
public int compare(AppInfo o1, AppInfo o2) {
if (o2.installTime == o1.installTime) {
return 0;
}
return o2.installTime > o1.installTime ? 1 : -1;
}
};
} else if (type == 3) {
//按最后更新时间排序
comparator = new Comparator<AppInfo>() {
@Override
public int compare(AppInfo o1, AppInfo o2) {
return Math.max(o2.installTime, o2.updateTime) > Math.max(o1.installTime, o1.updateTime) ? 1 : -1;
}
};
}

if (comparator != null) {
Collections.sort(appInfos, comparator);
}


return appInfos;
}
};
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.zzzmode.appopsx.ui.main;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.zzzmode.appopsx.R;
import com.zzzmode.appopsx.ui.core.LocalImageLoader;
import com.zzzmode.appopsx.ui.model.AppInfo;

/**
* Created by zl on 2017/5/7.
*/

public class AppItemViewHolder extends RecyclerView.ViewHolder {

ImageView imgIcon;
TextView tvName;

public AppItemViewHolder(View itemView) {
super(itemView);
imgIcon= (ImageView) itemView.findViewById(R.id.app_icon);
tvName= (TextView) itemView.findViewById(R.id.app_name);
}


public void bindData(AppInfo appInfo){
tvName.setText(appInfo.appName);
LocalImageLoader.load(imgIcon,appInfo);
}
}
23 changes: 22 additions & 1 deletion app/src/main/java/com/zzzmode/appopsx/ui/main/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.view.MenuItemCompat;
Expand All @@ -30,6 +31,7 @@
import com.zzzmode.appopsx.ui.analytics.ATracker;
import com.zzzmode.appopsx.ui.core.AppOpsx;
import com.zzzmode.appopsx.ui.core.Helper;
import com.zzzmode.appopsx.ui.main.backup.BackupActivity;
import com.zzzmode.appopsx.ui.model.AppInfo;
import com.zzzmode.appopsx.ui.model.AppOpEntry;
import com.zzzmode.appopsx.ui.widget.CommonDivderDecorator;
Expand Down Expand Up @@ -100,19 +102,24 @@ public void onRefresh() {

private void loadData(final boolean isFirst) {
boolean showSysApp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getBoolean("show_sysapp", false);
Helper.getInstalledApps(getApplicationContext(), showSysApp).subscribeOn(Schedulers.io())
Helper.getInstalledApps(getApplicationContext(), showSysApp).map(Helper.getSortComparator(getApplicationContext())).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()).subscribe(new ResourceObserver<List<AppInfo>>() {
@Override
public void onNext(List<AppInfo> value) {
adapter.showItems(value);
mSearchHandler.setBaseData(new ArrayList<AppInfo>(value));

ActivityCompat.invalidateOptionsMenu(MainActivity.this);

}

@Override
public void onError(Throwable e) {
e.printStackTrace();
mSwipeRefreshLayout.setRefreshing(false);
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();

ActivityCompat.invalidateOptionsMenu(MainActivity.this);
}

@Override
Expand All @@ -124,6 +131,8 @@ public void onComplete() {
if(isFirst){
mSwipeRefreshLayout.setEnabled(true);
}

ActivityCompat.invalidateOptionsMenu(MainActivity.this);
}
});
}
Expand All @@ -139,6 +148,10 @@ public boolean onOptionsItemSelected(MenuItem item) {
ATracker.send(AEvent.C_PERMISSION_LIST);
openSortPermission();
return true;
case R.id.action_backup:
ATracker.send(AEvent.C_BACKUP);
openConfigPerms();
return true;
default:
return super.onOptionsItemSelected(item);
}
Expand All @@ -152,6 +165,8 @@ public boolean onCreateOptionsMenu(Menu menu) {
final MenuItem settingsMenu=menu.findItem(R.id.action_setting);
final MenuItem premsMenu=menu.findItem(R.id.action_permission_sort);

menu.findItem(R.id.action_backup).setVisible(adapter != null && adapter.getItemCount()>0);

MenuItemCompat.setOnActionExpandListener(searchMenu, new MenuItemCompat.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
Expand Down Expand Up @@ -197,6 +212,12 @@ private void openSortPermission() {
startActivity(new Intent(this, PermissionGroupActivity.class));
}

private void openConfigPerms(){
Intent intent = new Intent(this, BackupActivity.class);
intent.putParcelableArrayListExtra(BackupActivity.EXTRA_APPS,new ArrayList<AppInfo>(adapter.getAppInfos()));
startActivity(intent);
}

private void resetAll() {
if (adapter != null && adapter.appInfos != null) {
final List<AppInfo> appInfos = adapter.appInfos;
Expand Down
Loading

0 comments on commit 387edaf

Please sign in to comment.