package de.theknut.xposedgelsettings.hooks.androidintegration;
import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import java.util.ArrayList;
import java.util.HashSet;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
import de.theknut.xposedgelsettings.R;
import de.theknut.xposedgelsettings.hooks.Common;
import de.theknut.xposedgelsettings.hooks.HooksBaseClass;
import de.theknut.xposedgelsettings.hooks.Utils;
import static de.robv.android.xposed.XposedHelpers.callMethod;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import static de.robv.android.xposed.XposedHelpers.getObjectField;
/**
* Created by Alexander Schulz on 29.07.2014.
*/
public class AppInfo extends HooksBaseClass {
static Context SettingsContext;
static Context XGELSContext;
static LayoutInflater inflater;
static ArrayList<String> hiddenApps;
public static void initAllHooks(LoadPackageParam lpparam) {
final String key = "hiddenapps";
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
findAndHookMethod("com.android.settings.applications.InstalledAppDetails", lpparam.classLoader, "onCreateView", LayoutInflater.class, ViewGroup.class, Bundle.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
if (DEBUG) log(param, "AndroidSettings: Add \"Hide app\" checkbox");
if (inflater == null) {
SettingsContext = (Context) callMethod(param.thisObject, "getActivity");
XGELSContext = SettingsContext.createPackageContext(Common.PACKAGE_NAME, Context.CONTEXT_IGNORE_SECURITY);
inflater = (LayoutInflater) XGELSContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
final SharedPreferences prefs = XGELSContext.getSharedPreferences(Common.PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
hiddenApps = new ArrayList<>(prefs.getStringSet(key, new HashSet<String>()));
Object mAppEntry = getObjectField(param.thisObject, "mAppEntry");
ApplicationInfo info = (ApplicationInfo) getObjectField(mAppEntry, "info");
// Application doesn't have a launch intent, nothing to do
Intent launchIntent = SettingsContext.getPackageManager().getLaunchIntentForPackage(info.packageName);
if (launchIntent == null) {
return;
}
CheckBox mNotificationSwitch = (CheckBox) getObjectField(param.thisObject, "mNotificationSwitch");
ViewGroup parent = (ViewGroup) mNotificationSwitch.getParent();
CheckBox checkbox = new CheckBox(parent.getContext());
checkbox.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
checkbox.setText(XGELSContext.getResources().getString(R.string.hide_app_switch_label));
checkbox.setTag(launchIntent.getComponent().flattenToString());
checkbox.setChecked(hiddenApps.contains(checkbox.getTag()));
checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
hiddenApps = new ArrayList<>(prefs.getStringSet(key, new HashSet<String>()));
if (isChecked) {
if (!hiddenApps.contains(buttonView.getTag())) {
// app is not in the list, so lets add it
hiddenApps.add((String) buttonView.getTag());
}
} else {
if (hiddenApps.contains(buttonView.getTag())) {
// app is in the list but the checkbox is no longer checked, we can remove it
hiddenApps.remove(buttonView.getTag());
}
}
Utils.saveToSettings(SettingsContext, key, hiddenApps, true);
}
});
parent.addView(checkbox);
}
});
} else {
findAndHookMethod("com.android.settings.applications.InstalledAppDetails", lpparam.classLoader, "onActivityCreated", Bundle.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
if (DEBUG) log(param, "AndroidSettings: Add \"Hide app\" checkbox");
if (inflater == null) {
SettingsContext = (Context) callMethod(param.thisObject, "getActivity");
XGELSContext = SettingsContext.createPackageContext(Common.PACKAGE_NAME, Context.CONTEXT_IGNORE_SECURITY);
inflater = (LayoutInflater) XGELSContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
final ContentResolver contentResolver = XGELSContext.getContentResolver();
final Uri hiddenAppsUri = Common.URI_SETTINGS_BASE.buildUpon().query("hiddenapps").build();
Cursor cursor = contentResolver.query(hiddenAppsUri, null, null, null, null);
if (cursor == null) return;
ArrayList<String> hiddenApps = new ArrayList<>();
while(cursor.moveToNext()) {
hiddenApps.add(cursor.getString(0));
}
cursor.close();
Object mAppEntry = getObjectField(param.thisObject, "mAppEntry");
ApplicationInfo info = (ApplicationInfo) getObjectField(mAppEntry, "info");
Intent launchIntent = SettingsContext.getPackageManager().getLaunchIntentForPackage(info.packageName);
// Application doesn't have a launch intent, nothing to do
if (launchIntent == null) {
return;
}
Button mForceStopButton = (Button) getObjectField(param.thisObject, "mForceStopButton");
ViewGroup parent = (ViewGroup) mForceStopButton.getParent().getParent();
CheckBox checkbox = new CheckBox(parent.getContext());
checkbox.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
checkbox.setText(XGELSContext.getResources().getString(R.string.hide_app_switch_label));
checkbox.setTag(launchIntent.getComponent().flattenToString());
checkbox.setChecked(hiddenApps.contains(checkbox.getTag()));
checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Cursor tmpCursor = contentResolver.query(hiddenAppsUri, null, null, null, null);
if (tmpCursor == null) return;
ArrayList<String> hiddenApps = new ArrayList<>();
while(tmpCursor.moveToNext()) {
hiddenApps.add(tmpCursor.getString(0));
}
tmpCursor.close();
if (isChecked) {
if (!hiddenApps.contains(buttonView.getTag())) {
// app is not in the list, so lets add it
hiddenApps.add((String) buttonView.getTag());
}
} else {
if (hiddenApps.contains(buttonView.getTag())) {
// app is in the list but the checkbox is no longer checked, we can remove it
hiddenApps.remove(buttonView.getTag());
}
}
ContentValues values = new ContentValues();
values.put("type", hiddenApps.getClass().toString());
values.put("value", hiddenApps.toString());
contentResolver.update(hiddenAppsUri, values, null, null);
SettingsContext.sendBroadcast(new Intent(Common.XGELS_ACTION_RELOAD_SETTINGS));
}
});
parent.addView(checkbox);
}
});
}
}
}