Initial implementation of auto-mount, WIP

Will manually merge working product into /master
This commit is contained in:
d8ahazard 2016-08-31 16:52:42 -05:00
parent 3a238e9d4b
commit fc5c9647d8
35 changed files with 735 additions and 45 deletions

View File

@ -1,11 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest package="com.topjohnwu.magisk" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
xmlns:tools="http://schemas.android.com/tools"> package="com.topjohnwu.magisk">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
<application <application
android:allowBackup="true" android:allowBackup="true"
@ -26,15 +31,25 @@
<activity <activity
android:name=".AboutActivity" android:name=".AboutActivity"
android:theme="@style/AppTheme.Transparent" /> android:theme="@style/AppTheme.Transparent" />
<provider <provider
android:name="android.support.v4.content.FileProvider" android:name="android.support.v4.content.FileProvider"
android:authorities="com.topjohnwu.magisk.provider" android:authorities="com.topjohnwu.magisk.provider"
android:grantUriPermissions="true" android:exported="false"
android:exported="false"> android:grantUriPermissions="true">
<meta-data <meta-data
android:name="android.support.FILE_PROVIDER_PATHS" android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" /> android:resource="@xml/file_paths" />
</provider> </provider>
<receiver android:name=".AutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".MonitorService"
android:exported="false" />
</application> </application>
</manifest> </manifest>

View File

@ -0,0 +1,154 @@
package com.topjohnwu.magisk;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import com.topjohnwu.magisk.utils.ApplicationAdapter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class AutoRootFragment extends ListFragment {
private PackageManager packageManager = null;
private List<ApplicationInfo> applist = null;
private ApplicationAdapter listadaptor = null;
public ListView listView;
public SharedPreferences prefs;
private View view;
List<String> arrayList;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.auto_root_fragment, container, false);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
listView = getListView();
packageManager = getActivity().getPackageManager();
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
if (!prefs.contains("autoapps")) {
SharedPreferences.Editor editor = prefs.edit();
Set<String> set = new HashSet<String>();
set.add("com.google.android.apps.walletnfcrel");
editor.putStringSet("autoapps", set);
editor.commit();
}
new LoadApplications().execute();
}
@Override
public void onResume() {
super.onResume();
new LoadApplications().execute();
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
ApplicationInfo app = applist.get(position);
ToggleApp(app.packageName, position, v);
}
private void ToggleApp(String appToCheck, int position, View v) {
Set<String> set = prefs.getStringSet("autoapps", null);
arrayList = new ArrayList<>(set);
Log.d("Magisk", "Trying to toggle for " + appToCheck + " stringset is " + arrayList.toString());
SharedPreferences.Editor editor = prefs.edit();
if (arrayList.contains(appToCheck)) {
Log.d("Magisk", "App is in array, removing");
for (int i = 0; i < arrayList.size(); i++) {
if (appToCheck.equals(arrayList.get(i))) {
arrayList.remove(i);
}
}
} else {
arrayList.add(appToCheck);
}
Set<String> set2 = new HashSet<String>(arrayList);
Log.d("Magisk", "Committing set, value is: " + set2);
editor.putStringSet("autoapps", set2);
editor.apply();
listadaptor.UpdateRootStatusView(position,v);
}
private List<ApplicationInfo> checkForLaunchIntent(List<ApplicationInfo> list) {
ArrayList<ApplicationInfo> applist = new ArrayList<ApplicationInfo>();
for (ApplicationInfo info : list) {
try {
if (null != packageManager.getLaunchIntentForPackage(info.packageName)) {
applist.add(info);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return applist;
}
private class LoadApplications extends AsyncTask<Void, Void, Void> {
private ProgressDialog progress = null;
@Override
protected Void doInBackground(Void... params) {
applist = checkForLaunchIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA));
listadaptor = new ApplicationAdapter(getActivity(),
R.layout.app_list_row, applist);
return null;
}
@Override
protected void onCancelled() {
super.onCancelled();
}
@Override
protected void onPostExecute(Void result) {
setListAdapter(listadaptor);
progress.dismiss();
super.onPostExecute(result);
}
@Override
protected void onPreExecute() {
progress = ProgressDialog.show(getActivity(), null,
"Loading application info...");
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
}

View File

@ -0,0 +1,16 @@
package com.topjohnwu.magisk;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class AutoStart extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("Magisk", "Received Boot call, attempting to start service");
Intent myIntent = new Intent(context, MonitorService.class);
context.startService(myIntent);
}
}

View File

@ -0,0 +1,198 @@
package com.topjohnwu.magisk;
import android.app.AppOpsManager;
import android.app.Fragment;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.os.Process;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.topjohnwu.magisk.utils.Shell;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
public class MonitorService extends Service
{
private static final String TAG = "Magisk";
private UsageStatsManager mUsageStatsManager;
private SharedPreferences prefs;
private Boolean disableroot;
private Boolean disablerootprev;
public static boolean isRecursionEnable = false;
private NotificationManager mNotifyMgr;
private CountDownTimer timer = new CountDownTimer(1000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
}
@Override
public void onFinish() {
CheckProcesses();
}
}.start();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!intent.hasExtra("disable")) {
new Thread(new Runnable() {
@Override
public void run() {
// DO your work here
// get the data
timer.start();
}
}).start();
return START_STICKY;
} else return STOP_FOREGROUND_REMOVE;
}
@Override
public void onDestroy() {
Log.d(TAG, "Destroyah!");
android.os.Process.killProcess(android.os.Process.myPid());
super.onDestroy();
}
private boolean getStats(Set<String> seti) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
boolean inStats = false;
UsageStatsManager lUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
if (seti != null) {
ArrayList<String> statList = new ArrayList<>(seti);
for (int i = 0; i < statList.size(); i++) {
if (isAppForeground(statList.get(i))) {
inStats = (isAppForeground(statList.get(i)));
}
}
return inStats;
}
Log.d(TAG, "SDK check failed.");
}
return false;
}
protected boolean isAppForeground(String packageName) {
UsageStatsManager usageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
List<UsageStats> stats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 10, time);
String topPackageName = new String();
if (stats != null) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<>();
for (UsageStats usageStats : stats) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
topPackageName = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
return topPackageName.equals(packageName);
}
private void CheckProcesses() {
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
if (prefs.getBoolean("autoRootEnable", false)) {
Set<String> set = prefs.getStringSet("autoapps", null);
ArrayList<String> arrayList = null;
if (set != null) {
disableroot = getStats(set);
}
if (disableroot != disablerootprev) {
String rootstatus = (disableroot ? "disabled" : "enabled");
Shell.su((disableroot ? "setprop magisk.root 0" : "setprop magisk.root 1"));
mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder;
mNotifyMgr.cancelAll();
if (disableroot) {
timer.cancel();
this.stopSelf();
Intent intent = new Intent(this, WelcomeActivity.class);
intent.putExtra("relaunch", "relaunch");
PendingIntent pendingIntent = PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(disableroot ? R.drawable.ic_stat_notification_autoroot_off : R.drawable.ic_stat_notification_autoroot_on)
.setContentIntent(pendingIntent)
.setContentTitle("Auto-root status changed")
.setContentText("Auto root has been " + rootstatus + "! Tap to re-enable when done.");
} else {
mBuilder =
new NotificationCompat.Builder(this)
.setAutoCancel(true)
.setSmallIcon(disableroot ? R.drawable.ic_stat_notification_autoroot_off : R.drawable.ic_stat_notification_autoroot_on)
.setContentTitle("Auto-root status changed")
.setContentText("Auto root has been " + rootstatus + "!");
}
// Builds the notification and issues it.
int mNotificationId = 001;
mNotifyMgr.notify(mNotificationId, mBuilder.build());
}
disablerootprev = disableroot;
Log.d(TAG, "Check Processes finished, result is " + disableroot + " and settings say we should be " + prefs.getBoolean("autoRootEnable", false));
timer.start();
}
}
private boolean hasUsagePermission() {
AppOpsManager appOps = (AppOpsManager)
getSystemService(Context.APP_OPS_SERVICE);
int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
Process.myUid(), getPackageName());
return mode == AppOpsManager.MODE_ALLOWED;
}
}

View File

@ -1,8 +1,11 @@
package com.topjohnwu.magisk; package com.topjohnwu.magisk;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -25,33 +28,51 @@ import butterknife.ButterKnife;
public class RootFragment extends Fragment { public class RootFragment extends Fragment {
@BindView(R.id.progressBar) ProgressBar progressBar; public SharedPreferences prefs;
@BindView(R.id.progressBar)
@BindView(R.id.rootSwitchView) View rootToggleView; ProgressBar progressBar;
@BindView(R.id.selinuxSwitchView) View selinuxToggleView; @BindView(R.id.rootSwitchView)
@BindView(R.id.rootStatusView) View rootStatusView; View rootToggleView;
@BindView(R.id.safetynetStatusView) View safetynetStatusView; @BindView(R.id.autoRootSwitchView)
@BindView(R.id.selinuxStatusView) View selinuxStatusView; View autoRootToggleView;
@BindView(R.id.selinuxSwitchView)
@BindView(R.id.root_toggle) Switch rootToggle; View selinuxToggleView;
@BindView(R.id.selinux_toggle) Switch selinuxToggle; @BindView(R.id.rootStatusView)
View rootStatusView;
@BindView(R.id.root_status_container) View rootStatusContainer; @BindView(R.id.safetynetStatusView)
@BindView(R.id.root_status_icon) ImageView rootStatusIcon; View safetynetStatusView;
@BindView(R.id.root_status) TextView rootStatus; @BindView(R.id.selinuxStatusView)
View selinuxStatusView;
@BindView(R.id.selinux_status_container) View selinuxStatusContainer; @BindView(R.id.root_toggle)
@BindView(R.id.selinux_status_icon) ImageView selinuxStatusIcon; Switch rootToggle;
@BindView(R.id.selinux_status) TextView selinuxStatus; @BindView(R.id.auto_root_toggle)
Switch autoRootToggle;
@BindView(R.id.safety_net_status) TextView safetyNetStatus; @BindView(R.id.selinux_toggle)
@BindView(R.id.safety_net_icon) ImageView safetyNetStatusIcon; Switch selinuxToggle;
@BindView(R.id.root_status_container)
@BindColor(R.color.red500) int red500; View rootStatusContainer;
@BindColor(R.color.green500) int green500; @BindView(R.id.root_status_icon)
@BindColor(R.color.grey500) int grey500; ImageView rootStatusIcon;
@BindColor(R.color.accent) int accent; @BindView(R.id.root_status)
TextView rootStatus;
@BindView(R.id.selinux_status_container)
View selinuxStatusContainer;
@BindView(R.id.selinux_status_icon)
ImageView selinuxStatusIcon;
@BindView(R.id.selinux_status)
TextView selinuxStatus;
@BindView(R.id.safety_net_status)
TextView safetyNetStatus;
@BindView(R.id.safety_net_icon)
ImageView safetyNetStatusIcon;
@BindColor(R.color.red500)
int red500;
@BindColor(R.color.green500)
int green500;
@BindColor(R.color.grey500)
int grey500;
@BindColor(R.color.accent)
int accent;
int statusOK = R.drawable.ic_check_circle; int statusOK = R.drawable.ic_check_circle;
int statusError = R.drawable.ic_error; int statusError = R.drawable.ic_error;
int statusUnknown = R.drawable.ic_help; int statusUnknown = R.drawable.ic_help;
@ -63,10 +84,25 @@ public class RootFragment extends Fragment {
ButterKnife.bind(this, view); ButterKnife.bind(this, view);
new updateUI().execute(); new updateUI().execute();
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
rootToggle.setOnClickListener(toggle -> { rootToggle.setOnClickListener(toggle -> {
Shell.su(((CompoundButton) toggle).isChecked() ? "setprop magisk.root 1" : "setprop magisk.root 0"); Shell.su(((CompoundButton) toggle).isChecked() ? "setprop magisk.root 1" : "setprop magisk.root 0");
new Handler().postDelayed(() -> new updateUI().execute(), 1000); new Handler().postDelayed(() -> new updateUI().execute(), 1000);
if (!((CompoundButton) toggle).isChecked()) {
autoRootToggle.setChecked(false);
}
});
autoRootToggle.setOnClickListener(toggle -> {
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("autoRootEnable", ((CompoundButton) toggle).isChecked());
editor.commit();
if (((CompoundButton) toggle).isChecked()) {
Intent myIntent = new Intent(getActivity(), MonitorService.class);
getActivity().startService(myIntent);
}
}); });
selinuxToggle.setOnClickListener(toggle -> { selinuxToggle.setOnClickListener(toggle -> {
@ -77,7 +113,13 @@ public class RootFragment extends Fragment {
return view; return view;
} }
private class updateUI extends AsyncTask<Void, Void, Void> { @Override
public void onResume() {
super.onResume();
new updateUI().execute();
}
public class updateUI extends AsyncTask<Void, Void, Void> {
@Override @Override
protected Void doInBackground(Void... voids) { protected Void doInBackground(Void... voids) {
@ -98,6 +140,7 @@ public class RootFragment extends Fragment {
if (Shell.rootAccess()) { if (Shell.rootAccess()) {
rootToggleView.setVisibility(View.VISIBLE); rootToggleView.setVisibility(View.VISIBLE);
autoRootToggleView.setVisibility(View.VISIBLE);
selinuxToggleView.setVisibility(View.VISIBLE); selinuxToggleView.setVisibility(View.VISIBLE);
} }
@ -183,7 +226,7 @@ public class RootFragment extends Fragment {
rootToggle.setChecked(true); rootToggle.setChecked(true);
safetyNetStatusIcon.setImageResource(statusError); safetyNetStatusIcon.setImageResource(statusError);
safetyNetStatus.setText(R.string.root_system_info); safetyNetStatus.setText(R.string.root_system_info);
autoRootToggleView.setVisibility(View.GONE);
rootToggleView.setVisibility(View.GONE); rootToggleView.setVisibility(View.GONE);
selinuxToggleView.setVisibility(View.GONE); selinuxToggleView.setVisibility(View.GONE);
break; break;

View File

@ -1,11 +1,16 @@
package com.topjohnwu.magisk; package com.topjohnwu.magisk;
import android.Manifest; import android.Manifest;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.annotation.IdRes; import android.support.annotation.IdRes;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView; import android.support.design.widget.NavigationView;
@ -31,9 +36,12 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
private final Handler mDrawerHandler = new Handler(); private final Handler mDrawerHandler = new Handler();
@BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.toolbar)
@BindView(R.id.drawer_layout) DrawerLayout drawer; Toolbar toolbar;
@BindView(R.id.nav_view) NavigationView navigationView; @BindView(R.id.drawer_layout)
DrawerLayout drawer;
@BindView(R.id.nav_view)
NavigationView navigationView;
@IdRes @IdRes
private int mSelectedId = R.id.magisk; private int mSelectedId = R.id.magisk;
@ -43,16 +51,25 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome); setContentView(R.layout.activity_welcome);
ButterKnife.bind(this); ButterKnife.bind(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} }
// Startups // Startups
PreferenceManager.setDefaultValues(this, R.xml.defaultpref, false);
if (!isMyServiceRunning(MonitorService.class)) {
Intent myIntent = new Intent(getApplication(), MonitorService.class);
getApplication().startService(myIntent);
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0); requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
} }
if (!hasPermission()) {
startActivityForResult(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS), 100);
}
new Utils.Initialize(this).execute(); new Utils.Initialize(this).execute();
new Utils.CheckUpdates(this).execute(); new Utils.CheckUpdates(this).execute();
new Utils.LoadModules(this).execute(); new Utils.LoadModules(this).execute();
@ -85,6 +102,9 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
} }
navigationView.setNavigationItemSelectedListener(this); navigationView.setNavigationItemSelectedListener(this);
if (getIntent().hasExtra("relaunch")) {
navigate(R.id.root);
}
} }
@ -114,6 +134,25 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
return true; return true;
} }
private boolean hasPermission() {
AppOpsManager appOps = (AppOpsManager)
getSystemService(Context.APP_OPS_SERVICE);
int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
android.os.Process.myUid(), getPackageName());
return mode == AppOpsManager.MODE_ALLOWED;
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
private void navigate(final int itemId) { private void navigate(final int itemId) {
Fragment navFragment = null; Fragment navFragment = null;
String tag = ""; String tag = "";
@ -128,6 +167,11 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
tag = "root"; tag = "root";
navFragment = new RootFragment(); navFragment = new RootFragment();
break; break;
case R.id.autoroot:
setTitle(R.string.auto_root);
tag = "ic_autoroot";
navFragment = new AutoRootFragment();
break;
case R.id.modules: case R.id.modules:
setTitle(R.string.modules); setTitle(R.string.modules);
tag = "modules"; tag = "modules";
@ -154,4 +198,6 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
} }
} }
} }
} }

View File

@ -0,0 +1,107 @@
package com.topjohnwu.magisk.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class ApplicationAdapter extends ArrayAdapter<ApplicationInfo> {
private List<ApplicationInfo> appsList = null;
private Context context;
private PackageManager packageManager;
public ArrayList arrayList;
public SharedPreferences prefs;
public ApplicationAdapter(Context context, int textViewResourceId,
List<ApplicationInfo> appsList) {
super(context, textViewResourceId, appsList);
this.context = context;
this.appsList = appsList;
packageManager = context.getPackageManager();
}
@Override
public int getCount() {
return ((null != appsList) ? appsList.size() : 0);
}
@Override
public ApplicationInfo getItem(int position) {
return ((null != appsList) ? appsList.get(position) : null);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
if (null == view) {
LayoutInflater layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.app_list_row, null);
}
ApplicationInfo applicationInfo = appsList.get(position);
if (null != applicationInfo) {
TextView appName = (TextView) view.findViewById(R.id.app_name);
TextView packageName = (TextView) view.findViewById(R.id.app_paackage);
ImageView iconview = (ImageView) view.findViewById(R.id.app_icon);
ImageView statusview = (ImageView) view.findViewById(R.id.app_status);
appName.setText(applicationInfo.loadLabel(packageManager));
packageName.setText(applicationInfo.packageName);
iconview.setImageDrawable(applicationInfo.loadIcon(packageManager));
if (CheckApp(applicationInfo.packageName)) {
statusview.setImageDrawable(this.context.getDrawable(R.drawable.root));
} else {
statusview.setImageDrawable(null);
}
}
return view;
}
public void UpdateRootStatusView(int position, View convertView) {
View view = convertView;
if (null == view) {
LayoutInflater layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.app_list_row, null);
}
ApplicationInfo applicationInfo = appsList.get(position);
if (null != applicationInfo) {
ImageView statusview = (ImageView) view.findViewById(R.id.app_status);
if (CheckApp(applicationInfo.packageName)) {
statusview.setImageDrawable(this.context.getDrawable(R.drawable.root));
} else {
statusview.setImageDrawable(null);
}
}
}
private boolean CheckApp(String appToCheck) {
Set<String> set = prefs.getStringSet("autoapps", null);
arrayList = new ArrayList<>(set);
return arrayList.toString().contains(appToCheck);
}
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="400.0"
android:viewportWidth="400.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillAlpha="1.00" android:fillColor="#000000" android:pathData="M200.6,24.2C231.8,24.2 263,33 289.6,49.5C304.7,58.8 318.2,70.7 329.8,84.1C351.5,109.6 365.2,141.7 368.8,175C373.6,217.4 361.5,261.5 335.5,295.5C334.2,297.1 332.8,298.7 331.9,300.7C341.7,310.1 351,320 360.9,329.3C322.7,339.3 284.5,349.6 246.3,359.9C256.4,323.5 266,287 275.7,250.5C262.4,250.5 249.1,250.5 235.8,250.5C228.5,269.8 221.2,289.1 214.1,308.4C205.9,308.6 197.8,308.5 189.6,308.5C188.4,306.7 187.1,304.9 185.9,303C192.4,285.5 199.1,268 205.6,250.5C189.5,250.6 173.4,250.3 157.4,250.6C150.4,270 142.9,289.2 135.8,308.5C129.8,308.5 123.9,308.4 117.9,308.6C130.4,317.8 144,325.6 158.9,330.3C171.9,334.6 185.6,336.6 199.4,336.7C199.4,349.4 199.3,362.1 199.4,374.8C165.8,374.9 132.2,364.5 104.4,345.6C91.7,337 80.3,326.5 70.2,314.9C48.5,289.4 34.8,257.3 31.2,224C26.3,180.4 39.2,134.9 66.8,100.7C67.2,99.9 67.7,99.2 68.1,98.4C58.3,88.9 49,79 39.1,69.7C77.3,59.7 115.6,49.4 153.7,39.1C143.6,75.7 133.8,112.5 124.1,149.3C137.9,149.3 151.7,149.2 165.5,149.3C172.9,130 180.2,110.6 187.3,91.2C195.5,90.8 203.7,91 211.8,91C213,92.8 214.3,94.6 215.5,96.3C209.1,114 202.3,131.6 195.8,149.2C211.8,149.3 227.8,149.2 243.9,149.3C251.2,129.9 258.3,110.3 265.8,90.9C271.5,90.8 277.3,91.6 282.9,90.4C280.2,89.5 278.1,87.7 275.9,86.1C254,70.7 227.4,62.2 200.6,62.3C200.6,49.6 200.7,36.9 200.6,24.2M292.5,100C286.4,116.4 280.2,132.8 274,149.3C280.9,149.2 287.8,149.3 294.7,149.2C296,150.8 297.3,152.4 298.6,153.9C297.1,162.1 295.7,170.3 294.3,178.5C283.9,178.5 273.4,178.5 262.9,178.5C257.5,192.7 252.1,206.9 246.9,221.2C258.7,221.3 270.5,221.1 282.3,221.3C283.5,222.9 284.8,224.4 286.1,225.9C284.9,233.7 283.4,241.4 282.1,249.1C281.6,251 283.6,252.1 284.6,253.3C291.5,259.8 297.7,266.9 304.8,273.1C312.9,262.1 319.6,250.1 324.2,237.3C334.3,208.7 334.2,176.7 323.7,148.3C317,130.1 306.4,113.4 292.5,100M95.2,125.9C86.2,138 79,151.4 74.5,165.8C65.3,194.4 66.4,226.3 77.6,254.2C84.6,271.5 95.1,287.4 108.7,300.1C114.9,283.6 121.3,267.1 127.2,250.5C121.5,250.5 115.8,250.5 110,250.5C108.6,250.4 106.7,251 105.8,249.5C104.5,247.9 102.3,246.3 102.9,244.1C104.2,236.5 105.5,228.9 106.8,221.2C117.4,221.2 128.1,221.4 138.7,221.1C143.9,206.9 149.3,192.7 154.6,178.5C142.9,178.4 131.1,178.6 119.3,178.4C117.6,177.3 116.4,175.3 115,173.8C116.3,165.8 117.9,157.9 119,150C118.3,148.2 116.6,147.1 115.3,145.7C108.6,139.2 102.3,132.1 95.2,125.9M168.8,221.2C184.8,221.2 200.8,221.3 216.8,221.2C222.2,207 227.5,192.8 232.8,178.5C216.8,178.5 200.7,178.5 184.6,178.5C179.4,192.8 174,207 168.8,221.2Z"/>
</vector>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/app_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="3dp"
android:scaleType="centerCrop" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/lynn"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingLeft="5dp"
android:paddingRight="50dp">
<TextView
android:id="@+id/app_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textStyle="bold" />
<TextView
android:id="@+id/app_paackage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"></RelativeLayout>
</LinearLayout>
<ImageView
android:id="@+id/app_status"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="3dp"
android:scaleType="centerCrop"
android:layout_gravity="right"
android:layout_alignParentEnd="true" />
</RelativeLayout>
</LinearLayout>

View File

@ -0,0 +1,10 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>

View File

@ -30,4 +30,14 @@
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1"/> android:layout_weight="1"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_margin="16dp"
android:clickable="true"
android:src="@drawable/ic_add"
/>
</LinearLayout> </LinearLayout>

View File

@ -34,6 +34,24 @@
android:text="@string/root_toggle" android:text="@string/root_toggle"
android:textSize="16sp"/> android:textSize="16sp"/>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="@+id/autoRootSwitchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="2dp"
android:visibility="gone"
app:cardCornerRadius="0dp">
<Switch
android:id="@+id/auto_root_toggle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:checked="true"
android:text="@string/auto_root"
android:textSize="16sp"/>
</android.support.v7.widget.CardView> </android.support.v7.widget.CardView>
<android.support.v7.widget.CardView <android.support.v7.widget.CardView

View File

@ -15,6 +15,11 @@
android:icon="@drawable/root" android:icon="@drawable/root"
android:title="@string/root"/> android:title="@string/root"/>
<item
android:id="@+id/autoroot"
android:icon="@drawable/ic_autoroot"
android:title="@string/auto_root"/>
<item <item
android:id="@+id/modules" android:id="@+id/modules"
android:icon="@drawable/ic_extension" android:icon="@drawable/ic_extension"

View File

@ -21,6 +21,7 @@
<!--Root Fragment--> <!--Root Fragment-->
<string name="root_toggle">Root Toggle</string> <string name="root_toggle">Root Toggle</string>
<string name="auto_root">Auto Root</string>
<string name="selinux_toggle">SELinux Toggle</string> <string name="selinux_toggle">SELinux Toggle</string>
<string name="root_error">Root Error</string> <string name="root_error">Root Error</string>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:key="autoapps"
android:defaultValue="com.google.android.apps.walletnfcrel"
/>
</PreferenceScreen>