Browse Source

New mod: no password instead of fingerprint after boot

Better permission check
Better crash report
Release build config, reduced size
pull/109/head
Mikanoshi 2 years ago
parent
commit
d513fb5d68
50 changed files with 930 additions and 1221 deletions
  1. +5
    -0
      .idea/inspectionProfiles/Project_Default.xml
  2. +40
    -0
      README.html
  3. +22
    -10
      app/build.gradle
  4. +58
    -21
      app/proguard-rules.pro
  5. +10
    -2
      app/src/main/AndroidManifest.xml
  6. +2
    -1
      app/src/main/java/name/mikanoshi/customiuizer/AboutFragment.java
  7. +0
    -27
      app/src/main/java/name/mikanoshi/customiuizer/ActivityEx.java
  8. +39
    -4
      app/src/main/java/name/mikanoshi/customiuizer/MainActivity.java
  9. +44
    -21
      app/src/main/java/name/mikanoshi/customiuizer/MainApplication.java
  10. +92
    -68
      app/src/main/java/name/mikanoshi/customiuizer/MainFragment.java
  11. +9
    -6
      app/src/main/java/name/mikanoshi/customiuizer/MainModule.java
  12. +0
    -114
      app/src/main/java/name/mikanoshi/customiuizer/PreferenceFragmentBase.java
  13. +5
    -0
      app/src/main/java/name/mikanoshi/customiuizer/SharedPrefsProvider.java
  14. +2
    -0
      app/src/main/java/name/mikanoshi/customiuizer/SubFragment.java
  15. +18
    -4
      app/src/main/java/name/mikanoshi/customiuizer/SubFragmentWithSearch.java
  16. +54
    -41
      app/src/main/java/name/mikanoshi/customiuizer/crashreport/Dialog.java
  17. +43
    -0
      app/src/main/java/name/mikanoshi/customiuizer/crashreport/DialogInteraction.java
  18. +2
    -13
      app/src/main/java/name/mikanoshi/customiuizer/mods/Controls.java
  19. +32
    -49
      app/src/main/java/name/mikanoshi/customiuizer/mods/GlobalActions.java
  20. +0
    -1
      app/src/main/java/name/mikanoshi/customiuizer/mods/Launcher.java
  21. +2
    -1
      app/src/main/java/name/mikanoshi/customiuizer/mods/PackagePermissions.java
  22. +11
    -2
      app/src/main/java/name/mikanoshi/customiuizer/mods/System.java
  23. +1
    -0
      app/src/main/java/name/mikanoshi/customiuizer/prefs/CheckBoxPreferenceEx.java
  24. +1
    -0
      app/src/main/java/name/mikanoshi/customiuizer/prefs/ListPreferenceEx.java
  25. +1
    -2
      app/src/main/java/name/mikanoshi/customiuizer/prefs/PreferenceEx.java
  26. +2
    -1
      app/src/main/java/name/mikanoshi/customiuizer/subs/AppSelector.java
  27. +10
    -9
      app/src/main/java/name/mikanoshi/customiuizer/subs/ShortcutSelector.java
  28. +6
    -2
      app/src/main/java/name/mikanoshi/customiuizer/subs/SwipeGesture.java
  29. +4
    -5
      app/src/main/java/name/mikanoshi/customiuizer/utils/AppDataAdapter.java
  30. +10
    -13
      app/src/main/java/name/mikanoshi/customiuizer/utils/BitmapCachedLoader.java
  31. +35
    -0
      app/src/main/java/name/mikanoshi/customiuizer/utils/HelperReceiver.java
  32. +83
    -681
      app/src/main/java/name/mikanoshi/customiuizer/utils/Helpers.java
  33. +8
    -12
      app/src/main/java/name/mikanoshi/customiuizer/utils/ResolveInfoAdapter.java
  34. +2
    -5
      app/src/main/java/name/mikanoshi/customiuizer/utils/ShakeManager.java
  35. BIN
      app/src/main/res/drawable-xxhdpi-v4/alert.png
  36. BIN
      app/src/main/res/drawable-xxhdpi-v4/ic_miuize.png
  37. +0
    -40
      app/src/main/res/layout/activity_main.xml
  38. +18
    -7
      app/src/main/res/layout/fragment_about.xml
  39. +7
    -1
      app/src/main/res/layout/prefs_freedback.xml
  40. +8
    -8
      app/src/main/res/layout/prefs_swipe_gestures.xml
  41. +5
    -0
      app/src/main/res/menu/menu_mods.xml
  42. +196
    -0
      app/src/main/res/values-ru/strings.xml
  43. +0
    -2
      app/src/main/res/values/arrays.xml
  44. +0
    -5
      app/src/main/res/values/colors.xml
  45. +1
    -0
      app/src/main/res/values/dimens.xml
  46. +1
    -1
      app/src/main/res/values/ids.xml
  47. +24
    -36
      app/src/main/res/values/strings.xml
  48. +9
    -4
      app/src/main/res/values/styles.xml
  49. +1
    -1
      app/src/main/res/xml/prefs_main.xml
  50. +7
    -1
      app/src/main/res/xml/prefs_system.xml

+ 5
- 0
.idea/inspectionProfiles/Project_Default.xml View File

@ -1,9 +1,14 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="BooleanMethodIsAlwaysInverted" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CatchMayIgnoreException" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="Convert2Diamond" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="Convert2Lambda" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="IgnoreResultOfCall" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_reportAllNonLibraryCalls" value="false" />
<option name="callCheckString" value="java.io.InputStream,read|skip|available|markSupported,java.io.Reader,read|skip|ready|markSupported,java.lang.Boolean,.*,java.lang.Byte,.*,java.lang.Character,.*,java.lang.Double,.*,java.lang.Float,.*,java.lang.Integer,.*,java.lang.Long,.*,java.lang.Math,.*,java.lang.Object,equals|hashCode|toString,java.lang.Short,.*,java.lang.StrictMath,.*,java.lang.String,.*,java.lang.Thread,interrupted,java.math.BigInteger,.*,java.math.BigDecimal,.*,java.net.InetAddress,.*,java.net.URI,.*,java.util.Arrays,.*,java.util.List,of,java.util.Set,of,java.util.Map,of|ofEntries|entry,java.util.Collections,(?!addAll).*,java.util.UUID,.*,java.util.regex.Matcher,pattern|toMatchResult|start|end|group|groupCount|matches|find|lookingAt|quoteReplacement|replaceAll|replaceFirst|regionStart|regionEnd|hasTransparentBounds|hasAnchoringBounds|hitEnd|requireEnd,java.util.regex.Pattern,.*,java.util.stream.BaseStream,.*" />
</inspection_tool>
<inspection_tool class="NullableProblems" enabled="false" level="WARNING" enabled_by_default="false">
<option name="REPORT_NULLABLE_METHOD_OVERRIDES_NOTNULL" value="true" />
<option name="REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL" value="true" />


+ 40
- 0
README.html View File

@ -0,0 +1,40 @@
<div style="line-height: 150%;">
<center><img src="https://code.highspec.ru/customiuizer.png" /></center>
<h2>What is CustoMIUIzer?</h2>
CustoMIUIzer module contains a variety of mods that will provide additional functionality to your MIUI device. You have to have (Ed)Xposed Framework installed to use these mods. For more info about Xposed refer to the <a href="http://forum.xda-developers.com/xposed/xposed-installer-versions-changelog-t2714053" target="_blank">original thread</a> or <a href="https://github.com/ElderDrivers/EdXposed" target="_blank">github repo of EdXposed (for Android 9)</a>.
<h2>How to use CustoMIUIzer?</h2>
First you must have (Ed)Xposed Framework installed. After that enable CustoMIUIzer module in (Ed)Xposed Installer, set up mods you like and select 'Soft Reboot' from menu.
<h2>Backup functionality</h2>
CustoMIUIzer supports settings backup and restore using local backup on SDCard/internal storage (find it in main window's menu).<br>
It also supports automatic Google cloud backups (Android Backup Service).
<h2>Compatibility</h2>
Module was written, tested and is mainly intended for MIUI 10 on Android 9.<br>
Mods are not guaranteed to fully work on any other versions.
<h2>Troubleshooting</h2>
You can send a detailed report with a description of your problem from CustoMIUIzer itself or create new issue on <a href="https://code.highspec.ru/issues" target="_blank">issue tracker</a>.
<br><br>
<u>Common poblems</u><br><br>
<i>Module and mods were activated, device rebooted, but none of the mods are working.</i>
<hr>
Go to (Ed)Xposed Installer > Log and check information there.<br>
Find line "Loading modules from .../name.mikanoshi.customiuizer/...".<br>
If next line contains "File does not exist", then just reinstall CustoMIUIzer.<br>
If next line contains "This class requires resource-related hooks (which are disabled), skipping it.", then open (Ed)Xposed Installer > Settings and uncheck experimental option "Disabled resource hooks".<br>
If next line contains something else (error, exception, etc), then send detailed report from CustoMIUIzer and hope it can be fixed :)
<br><br>
<i>I sent a report from CustoMIUIzer and now waiting for response, where is it?</i>
<hr>
You will never get a response if you don't enter your contact info.<br>
Main CustoMIUIzer screen > Contact information. Write your e-mail, ICQ or XDA/4PDA nickname there.<br>
<br>
<a href="https://repo.xposed.info/module/name.mikanoshi.customiuizer" target="_blank">Xposed Module Repository</a>
<br>
</div>

+ 22
- 10
app/build.gradle View File

@ -1,26 +1,40 @@
apply plugin: 'com.android.application'
def acraVersion = '5.3.0-rc02'
def keystorePropertiesFile = rootProject.file("../keystore.properties");
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
signingConfigs {
dev {
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
v1SigningEnabled true
v2SigningEnabled false
}
}
compileSdkVersion 28
defaultConfig {
applicationId "name.mikanoshi.customiuizer"
minSdkVersion 24
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
includeCompileClasspath true
}
}
versionName "1.0.0"
signingConfig signingConfigs.dev
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.dev
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.dev
}
}
compileOptions {
@ -32,8 +46,6 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "ch.acra:acra-core:$acraVersion"
implementation "ch.acra:acra-dialog:$acraVersion"
compileOnly "com.google.auto.service:auto-service:1.0-rc4"
compileOnly 'de.robv.android.xposed:api:82'
compileOnly files('lib/miui.jar')
}
}

+ 58
- 21
app/proguard-rules.pro View File

@ -1,21 +1,58 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-verbose
-dontobfuscate
-dontpreverify
-allowaccessmodification
-keepattributes SourceFile,LineNumberTable,*Annotation*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * implements android.os.Parcelable {
static android.os.Parcelable$Creator CREATOR;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclassmembers class * extends java.lang.Enum {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-keep class name.mikanoshi.** { *; }
-dontwarn **
-dontnote **

+ 10
- 2
app/src/main/AndroidManifest.xml View File

@ -44,12 +44,13 @@
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<meta-data android:name="com.android.settings.category" android:value="com.android.settings.category.customiuizer" />
<meta-data android:name="com.android.settings.icon" android:resource="@drawable/ic_miuize" />
<meta-data android:name="com.android.settings.icon" android:resource="@drawable/ic_launcher" />
<meta-data android:name="com.android.settings.icon_tintable" android:value="true" />
<meta-data android:name="com.android.settings.title" android:resource="@string/app_name" />
</activity-alias>
<activity android:name=".CrashReportDialog"
<activity
android:name=".crashreport.Dialog"
android:theme="@style/Invisible"
android:launchMode="singleTask"
android:excludeFromRecents="true"
@ -62,6 +63,13 @@
android:grantUriPermissions="true"
android:exported="true" />
<receiver android:name=".utils.HelperReceiver" android:exported="true">
<intent-filter>
<action android:name="name.mikanoshi.customiuizer.SAVEEXCEPTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<meta-data android:name="xposedmodule" android:value="true" />
<meta-data android:name="xposedminversion" android:value="82+" />
<meta-data android:name="xposeddescription" android:value="Customize MIUI to your liking" />


+ 2
- 1
app/src/main/java/name/mikanoshi/customiuizer/AboutFragment.java View File

@ -26,6 +26,7 @@ public class AboutFragment extends SubFragment {
Preference donatePagePreference = findPreference("pref_key_donatepage");
donatePagePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
@SuppressWarnings("deprecation")
public boolean onPreferenceClick(Preference pref) {
if (getResources().getConfiguration().locale.getISO3Language().contains("ru"))
Helpers.openURL(act, "https://mikanoshi.name/donate/");
@ -36,7 +37,7 @@ public class AboutFragment extends SubFragment {
});
//Add version name to support title
try {
if (getView() != null) try {
TextView version = getView().findViewById(R.id.about_version);
version.setText(String.format(getResources().getString(R.string.about_version), act.getPackageManager().getPackageInfo(act.getPackageName(), 0).versionName));
} catch (Throwable e) {


+ 0
- 27
app/src/main/java/name/mikanoshi/customiuizer/ActivityEx.java View File

@ -4,11 +4,7 @@ import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Fragment;
import android.app.backup.BackupManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import name.mikanoshi.customiuizer.utils.Helpers;
@ -17,30 +13,12 @@ import name.mikanoshi.customiuizer.utils.Helpers;
public class ActivityEx extends Activity {
public int mThemeBackground = 1;
public boolean launch = true;
SharedPreferences.OnSharedPreferenceChangeListener prefsChanged;
@SuppressWarnings("ConstantConditions")
protected void onCreate(Bundle savedInstanceState) {
setTheme(getResources().getIdentifier("Theme.Light.Settings", "style", "miui"));
getTheme().applyStyle(R.style.MIUIPrefs, true);
super.onCreate(savedInstanceState);
Helpers.prefs = getSharedPreferences(Helpers.prefsName, Context.MODE_PRIVATE);
prefsChanged = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPrefs, String key) {
Log.w("prefs", "Changed: " + key);
requestBackup();
Object val = sharedPrefs.getAll().get(key);
String path = "/";
if (val instanceof String)
path = "/string/";
else if (val instanceof Integer)
path = "/integer/";
getContentResolver().notifyChange(Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + path + key), null);
}
};
Helpers.prefs.registerOnSharedPreferenceChangeListener(prefsChanged);
mThemeBackground = Integer.parseInt(Helpers.prefs.getString("pref_key_miuizer_material_background", "1"));
//if (mThemeBackground == 2) getTheme().applyStyle(R.style.MaterialThemeDark, true);
@ -55,11 +33,6 @@ public class ActivityEx extends Activity {
super.onBackPressed();
}
protected void onDestroy() {
Helpers.prefs.unregisterOnSharedPreferenceChangeListener(prefsChanged);
super.onDestroy();
}
@SuppressWarnings("ConstantConditions")
public void updateTheme(int newBkg) {
int newThemeBackground;


+ 39
- 4
app/src/main/java/name/mikanoshi/customiuizer/MainActivity.java View File

@ -1,32 +1,59 @@
package name.mikanoshi.customiuizer;
import android.Manifest;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
import name.mikanoshi.customiuizer.utils.Helpers;
public class MainActivity extends ActivityEx {
public static final int REQUEST_BACKUP_PERMISSIONS = 1;
MainFragment mainFrag = null;
SharedPreferences.OnSharedPreferenceChangeListener prefsChanged;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Helpers.dataPath = getFilesDir().getPath();
Helpers.externalPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/CustoMIUIzer/";
Helpers.prefs = getSharedPreferences(Helpers.prefsName, Context.MODE_PRIVATE);
super.onCreate(savedInstanceState);
prefsChanged = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPrefs, String key) {
Log.w("prefs", "Changed: " + key);
requestBackup();
Object val = sharedPrefs.getAll().get(key);
String path = "/";
if (val instanceof String)
path = "/string/";
else if (val instanceof Integer)
path = "/integer/";
getContentResolver().notifyChange(Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + path + key), null);
}
};
Helpers.prefs.registerOnSharedPreferenceChangeListener(prefsChanged);
if (!launch) return;
mainFrag = new MainFragment();
getFragmentManager().beginTransaction().replace(R.id.fragment_container, mainFrag).commit();
}
protected void onDestroy() {
Helpers.prefs.unregisterOnSharedPreferenceChangeListener(prefsChanged);
super.onDestroy();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_BACKUP_PERMISSIONS:
case Helpers.REQUEST_PERMISSIONS_BACKUP:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
mainFrag.backupSettings(this);
else if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE))
@ -34,6 +61,14 @@ public class MainActivity extends ActivityEx {
else
Toast.makeText(this, "You'll have to manually enable permission for this option now. Good job!", Toast.LENGTH_LONG).show();
break;
case Helpers.REQUEST_PERMISSIONS_RESTORE:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
mainFrag.restoreSettings(this);
else if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE))
Toast.makeText(this, "Do you want to restore backup or not?", Toast.LENGTH_SHORT).show();
else
Toast.makeText(this, "You'll have to manually enable permission for this option now. Good job!", Toast.LENGTH_LONG).show();
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}


+ 44
- 21
app/src/main/java/name/mikanoshi/customiuizer/MainApplication.java View File

@ -3,33 +3,32 @@ package name.mikanoshi.customiuizer;
import android.app.Application;
import android.content.Context;
import com.google.auto.service.AutoService;
import org.acra.ACRA;
import org.acra.ReportField;
import org.acra.annotation.AcraCore;
import org.acra.annotation.AcraDialog;
import org.acra.collector.ApplicationStartupCollector;
import org.acra.collector.ConfigurationCollector;
import org.acra.collector.CustomDataCollector;
import org.acra.collector.DeviceFeaturesCollector;
import org.acra.collector.DisplayManagerCollector;
import org.acra.collector.LogCatCollector;
import org.acra.collector.MemoryInfoCollector;
import org.acra.collector.PackageManagerCollector;
import org.acra.collector.ReflectionCollector;
import org.acra.collector.SettingsCollector;
import org.acra.collector.SharedPreferencesCollector;
import org.acra.collector.SimpleValuesCollector;
import org.acra.collector.StacktraceCollector;
import org.acra.collector.ThreadCollector;
import org.acra.collector.TimeCollector;
import org.acra.config.CoreConfigurationBuilder;
import org.acra.data.StringFormat;
import org.acra.plugins.SimplePluginLoader;
import miui.core.SdkManager;
import name.mikanoshi.customiuizer.crashreport.DialogInteraction;
import name.mikanoshi.customiuizer.utils.Helpers;
import static org.acra.ReportField.*;
@AcraCore(
reportContent = { REPORT_ID, APP_VERSION_CODE, APP_VERSION_NAME, PACKAGE_NAME, FILE_PATH, PHONE_MODEL, BRAND, PRODUCT, ANDROID_VERSION,
BUILD, TOTAL_MEM_SIZE, AVAILABLE_MEM_SIZE, CUSTOM_DATA, STACK_TRACE, INITIAL_CONFIGURATION, CRASH_CONFIGURATION, DISPLAY, USER_COMMENT, USER_EMAIL,
USER_APP_START_DATE, USER_CRASH_DATE, DUMPSYS_MEMINFO, LOGCAT, INSTALLATION_ID, DEVICE_FEATURES, ENVIRONMENT, SHARED_PREFERENCES,
SETTINGS_SYSTEM, SETTINGS_SECURE, SETTINGS_GLOBAL },
sharedPreferencesName = "customiuizer_prefs",
//additionalSharedPreferences = {"customiuizer_prefs"},
logcatArguments = { "-t", "500", "-v", "time" },
buildConfigClass = BuildConfig.class,
reportFormat = StringFormat.JSON
)
@AcraDialog(
reportDialogClass = CrashReportDialog.class
)
public class MainApplication extends Application {
public MainApplication() {
@ -45,8 +44,32 @@ public class MainApplication extends Application {
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
ACRA.init(this);
ACRA.DEV_LOGGING = true;
CoreConfigurationBuilder builder = new CoreConfigurationBuilder(this).setPluginLoader(new SimplePluginLoader(
ConfigurationCollector.class,
ApplicationStartupCollector.class,
ConfigurationCollector.class,
CustomDataCollector.class,
DeviceFeaturesCollector.class,
DisplayManagerCollector.class,
LogCatCollector.class,
MemoryInfoCollector.class,
PackageManagerCollector.class,
ReflectionCollector.class,
SettingsCollector.class,
SharedPreferencesCollector.class,
SimpleValuesCollector.class,
StacktraceCollector.class,
ThreadCollector.class,
TimeCollector.class,
DialogInteraction.class
));
builder.setBuildConfigClass(BuildConfig.class).setReportFormat(StringFormat.JSON).setLogcatArguments("-t", "500", "-v", "time").setSharedPreferencesName(Helpers.prefsName);
builder.setReportContent(REPORT_ID, APP_VERSION_CODE, APP_VERSION_NAME, PACKAGE_NAME, FILE_PATH, PHONE_MODEL, BRAND, PRODUCT, ANDROID_VERSION,
BUILD, TOTAL_MEM_SIZE, AVAILABLE_MEM_SIZE, CUSTOM_DATA, STACK_TRACE, INITIAL_CONFIGURATION, CRASH_CONFIGURATION, DISPLAY, USER_COMMENT, USER_EMAIL,
USER_APP_START_DATE, USER_CRASH_DATE, DUMPSYS_MEMINFO, LOGCAT, INSTALLATION_ID, DEVICE_FEATURES, ENVIRONMENT, SHARED_PREFERENCES,
SETTINGS_SYSTEM, SETTINGS_SECURE, SETTINGS_GLOBAL);
ACRA.init(this, builder);
}
}

+ 92
- 68
app/src/main/java/name/mikanoshi/customiuizer/MainFragment.java View File

@ -1,6 +1,5 @@
package name.mikanoshi.customiuizer;
import android.animation.LayoutTransition;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ComponentName;
@ -10,6 +9,7 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
@ -17,12 +17,14 @@ import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.ImageView;
import android.widget.Toast;
import org.acra.ACRA;
@ -62,28 +64,9 @@ public class MainFragment extends PreferenceFragmentBase {
private Runnable showUpdateNotification = new Runnable() {
@Override
public void run() {
if (isFragmentReady(getActivity())) try {
TextView update = getActivity().findViewById(R.id.update);
update.setText(R.string.update_available);
update.setTextColor(getResources().getColor(android.R.color.background_light, getActivity().getTheme()));
FrameLayout updateFrame = getActivity().findViewById(R.id.updateFrame);
updateFrame.setLayoutTransition(new LayoutTransition());
updateFrame.setVisibility(View.VISIBLE);
updateFrame.setBackgroundColor(0xff252525);
updateFrame.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
Intent detailsIntent = new Intent();
detailsIntent.setComponent(new ComponentName("de.robv.android.xposed.installer", "de.robv.android.xposed.installer.DownloadDetailsActivity"));
detailsIntent.setData(Uri.fromParts("package", "com.sensetoolbox.six", null));
startActivity(detailsIntent);
} catch (Throwable e) {
Helpers.openURL(getActivity(), "http://sensetoolbox.com/6/download");
}
}
});
if (getView() != null) try {
ImageView alert = getView().findViewById(R.id.update_alert);
if (alert != null) alert.setVisibility(View.VISIBLE);
} catch (Throwable e) {}
}
};
@ -91,9 +74,9 @@ public class MainFragment extends PreferenceFragmentBase {
private Runnable hideUpdateNotification = new Runnable() {
@Override
public void run() {
if (isFragmentReady(getActivity())) try {
FrameLayout updateFrame = getActivity().findViewById(R.id.updateFrame);
updateFrame.setVisibility(View.GONE);
if (getView() != null) try {
ImageView alert = getView().findViewById(R.id.update_alert);
if (alert != null) alert.setVisibility(View.GONE);
} catch (Throwable e) {}
}
};
@ -113,6 +96,24 @@ public class MainFragment extends PreferenceFragmentBase {
ActionBar actionBar = getActionBar();
if (actionBar != null) actionBar.showSplitActionBar(false, false);
setImmersionMenuEnabled(true);
if (getView() != null)
if (getView().findViewById(R.id.update_alert) == null) {
Button more = getView().findViewById(getResources().getIdentifier("more", "id", "miui"));
if (more == null) return;
float density = getResources().getDisplayMetrics().density;
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.END | Gravity.TOP;
ImageView alert = new ImageView(getContext());
alert.setImageResource(R.drawable.alert);
alert.setAdjustViewBounds(true);
alert.setMaxWidth(Math.round(16 * density));
alert.setMaxHeight(Math.round(16 * density));
alert.setLayoutParams(lp);
alert.setId(R.id.update_alert);
alert.setVisibility(View.GONE);
((ViewGroup)more.getParent()).addView(alert);
}
}
@Override
@ -152,9 +153,11 @@ public class MainFragment extends PreferenceFragmentBase {
});
}
String backupPath = Environment.getExternalStorageDirectory().getAbsolutePath() + Helpers.externalFolder;
HttpURLConnection connection = null;
try {
URL url = new URL("http://sensetoolbox.com/last_build");
URL url = new URL("https://code.highspec.ru/Mikanoshi/CustoMIUIzer/raw/branch/master/last_build");
//URL url = new URL("https://code.highspec.ru/last_build");
connection = (HttpURLConnection)url.openConnection();
connection.setDefaultUseCaches(false);
connection.setUseCaches(false);
@ -168,32 +171,33 @@ public class MainFragment extends PreferenceFragmentBase {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
last_build = reader.readLine().trim();
} catch (Exception e) { e.printStackTrace(); }
} catch (Throwable t) { t.printStackTrace(); }
File tmp = new File(Helpers.externalPath);
if (!tmp.exists()) tmp.mkdirs();
try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(Helpers.externalPath + "last_build", false))) {
File tmp = new File(backupPath);
if (!tmp.exists()) //noinspection ResultOfMethodCallIgnored
tmp.mkdirs();
try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(backupPath + "last_build", false))) {
writer.write(last_build);
} catch (Exception e) { e.printStackTrace(); }
} catch (Throwable t) { t.printStackTrace(); }
}
} catch (Exception e) {}
} catch (Throwable t) {}
try {
if (connection != null) connection.disconnect();
} catch (Exception e) {}
} catch (Throwable t) {}
try (InputStream inputFile = new FileInputStream(Helpers.externalPath + "last_build")) {
try (InputStream inputFile = new FileInputStream(backupPath + "last_build")) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputFile));
int last_build = 0;
try {
last_build = Integer.parseInt(reader.readLine().trim());
} catch (Exception e) {}
} catch (Throwable t) {}
if (last_build != 0 && Helpers.buildVersion < last_build)
if (last_build != 0 && BuildConfig.VERSION_CODE < last_build)
handler.post(showUpdateNotification);
else
handler.post(hideUpdateNotification);
} catch (Exception e) {}
} catch (Throwable t) {}
}
}).start();
@ -217,7 +221,7 @@ public class MainFragment extends PreferenceFragmentBase {
ListPreference.OnPreferenceChangeListener changeBackgroundColor = new ListPreference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (act != null & !act.isFinishing()) ((ActivityEx)act).updateTheme(Integer.parseInt((String)newValue));
if (act != null && !act.isFinishing()) ((ActivityEx)act).updateTheme(Integer.parseInt((String)newValue));
return true;
}
};
@ -268,9 +272,27 @@ public class MainFragment extends PreferenceFragmentBase {
return true;
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
menu.getItem(0).setVisible(false);
if (getView() == null) return;
ImageView alert = getView().findViewById(R.id.update_alert);
if (alert != null && alert.isShown()) menu.getItem(0).setVisible(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.get_update:
try {
Intent detailsIntent = new Intent("de.robv.android.xposed.installer.DOWNLOAD_DETAILS");
detailsIntent.addCategory(Intent.CATEGORY_DEFAULT);
detailsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
detailsIntent.setData(Uri.fromParts("package", "name.mikanoshi.customiuizer", null));
startActivity(detailsIntent);
} catch (Throwable e) {
Helpers.openURL(getActivity(), "https://code.highspec.ru/Mikanoshi/CustoMIUIzer/releases");
}
case R.id.xposedinstaller:
if (!Helpers.isXposedInstallerInstalled(getContext())) {
Toast.makeText(getContext(), R.string.xposed_not_found, Toast.LENGTH_LONG).show();
@ -279,19 +301,17 @@ public class MainFragment extends PreferenceFragmentBase {
Intent intent = getContext().getPackageManager().getLaunchIntentForPackage("com.solohsu.android.edxp.manager");
try {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
if (intent != null) intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
getContext().startActivity(intent);
return true;
} catch (Throwable e1) {
intent = new Intent("de.robv.android.xposed.installer.OPEN_SECTION");
intent.setPackage("de.robv.android.xposed.installer");
intent.putExtra("section", "modules");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
intent = getContext().getPackageManager().getLaunchIntentForPackage("de.robv.android.xposed.installer");
if (intent != null) intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
try {
getContext().startActivity(intent);
return true;
} catch (Throwable e2) {
Toast.makeText(getContext(), R.string.xposed_not_found, Toast.LENGTH_LONG).show();;
Toast.makeText(getContext(), R.string.xposed_not_found, Toast.LENGTH_LONG).show();
}
return false;
}
@ -322,15 +342,16 @@ public class MainFragment extends PreferenceFragmentBase {
args.putInt("baseResId", R.layout.fragment_about);
openSubFragment(new AboutFragment(), args, Helpers.SettingsType.Preference, Helpers.ActionBarType.HomeUp, R.string.app_about, R.xml.prefs_about);
return true;
};
}
return super.onOptionsItemSelected(item);
}
public void backupSettings(Activity act) {
if (!Helpers.preparePathForBackup(act, Helpers.backupPath)) return;
String backupPath = Environment.getExternalStorageDirectory().getAbsolutePath() + Helpers.externalFolder;
if (!Helpers.preparePathForBackup(act, backupPath)) return;
ObjectOutputStream output = null;
try {
output = new ObjectOutputStream(new FileOutputStream(Helpers.backupPath + Helpers.backupFile));
output = new ObjectOutputStream(new FileOutputStream(backupPath + Helpers.backupFile));
output.writeObject(Helpers.prefs.getAll());
AlertDialog.Builder alert = new AlertDialog.Builder(act);
@ -362,10 +383,13 @@ public class MainFragment extends PreferenceFragmentBase {
}
}
@SuppressWarnings("unchecked")
public void restoreSettings(final Activity act) {
if (!Helpers.checkStoragePerm(act, Helpers.REQUEST_PERMISSIONS_RESTORE)) return;
if (!Helpers.checkStorageReadable(act)) return;
ObjectInputStream input = null;
try {
input = new ObjectInputStream(new FileInputStream(Helpers.backupPath + Helpers.backupFile));
input = new ObjectInputStream(new FileInputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + Helpers.externalFolder + Helpers.backupFile));
Map<String, ?> entries = (Map<String, ?>)input.readObject();
if (entries == null || entries.isEmpty()) throw new RuntimeException("Cannot read entries");
@ -401,7 +425,8 @@ public class MainFragment extends PreferenceFragmentBase {
}
});
alert.show();
} catch (Throwable e) {
} catch (Throwable t) {
t.printStackTrace();
AlertDialog.Builder alert = new AlertDialog.Builder(act);
alert.setTitle(R.string.warning);
alert.setMessage(R.string.storage_cannot_restore);
@ -427,7 +452,6 @@ public class MainFragment extends PreferenceFragmentBase {
alert.setPositiveButton(R.string.do_restore, new DialogInterface.OnClickListener() {
@SuppressWarnings("unchecked")
public void onClick(DialogInterface dialog, int whichButton) {
if (!Helpers.checkStorageReadable(act)) return;
restoreSettings(act);
}
});
@ -497,19 +521,19 @@ public class MainFragment extends PreferenceFragmentBase {
}
}
private void showNotYetDialog() {
try {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.info);
builder.setMessage(R.string.not_yet);
builder.setCancelable(true);
builder.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){}
});
AlertDialog dlg = builder.create();
dlg.show();
} catch (Throwable t) {
t.printStackTrace();
}
}
// private void showNotYetDialog() {
// try {
// AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// builder.setTitle(R.string.info);
// builder.setMessage(R.string.not_yet);
// builder.setCancelable(true);
// builder.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
// public void onClick(DialogInterface dialog, int whichButton){}
// });
// AlertDialog dlg = builder.create();
// dlg.show();
// } catch (Throwable t) {
// t.printStackTrace();
// }
// }
}

+ 9
- 6
app/src/main/java/name/mikanoshi/customiuizer/MainModule.java View File

@ -4,13 +4,12 @@ import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.IXposedHookZygoteInit;
import de.robv.android.xposed.XSharedPreferences;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
import name.mikanoshi.customiuizer.mods.Launcher;
import name.mikanoshi.customiuizer.mods.Controls;
import name.mikanoshi.customiuizer.mods.System;
import name.mikanoshi.customiuizer.mods.GlobalActions;
import name.mikanoshi.customiuizer.mods.Launcher;
import name.mikanoshi.customiuizer.mods.PackagePermissions;
import name.mikanoshi.customiuizer.mods.Various;
import name.mikanoshi.customiuizer.utils.GlobalActions;
import name.mikanoshi.customiuizer.utils.Helpers;
import name.mikanoshi.customiuizer.utils.PackagePermissions;
@SuppressWarnings("WeakerAccess")
public class MainModule implements IXposedHookZygoteInit, IXposedHookLoadPackage {
@ -33,6 +32,7 @@ public class MainModule implements IXposedHookZygoteInit, IXposedHookLoadPackage
public static boolean pref_appdetails = false;
public static boolean pref_scramblepin = false;
public static boolean pref_securelock = false;
public static boolean pref_nopassword = false;
public void initZygote(StartupParam startParam) {
MODULE_PATH = startParam.modulePath;
@ -50,12 +50,14 @@ public class MainModule implements IXposedHookZygoteInit, IXposedHookLoadPackage
pref_powerflash = pref.getBoolean("pref_key_controls_powerflash", false);
pref_nolightup = pref.getBoolean("pref_key_system_nolightuponcharge", false);
pref_appdetails = pref.getBoolean("pref_key_various_appdetails", false);
pref_appsort = Integer.parseInt(MainModule.pref.getString("pref_key_various_appsort", "0"));
pref_appsort = Integer.parseInt(pref.getString("pref_key_various_appsort", "0"));
pref_scramblepin = pref.getBoolean("pref_key_system_scramblepin", false);
pref_securelock = pref.getBoolean("pref_key_system_securelock", false);
pref_etoasts = Integer.parseInt(MainModule.pref.getString("pref_key_system_iconlabletoasts", "1"));
pref_nopassword = pref.getBoolean("pref_key_system_nopassword", false);
pref_etoasts = Integer.parseInt(pref.getString("pref_key_system_iconlabletoasts", "1"));
if (pref_etoasts > 1) System.IconLabelToastsHook();
GlobalActions.setupUnhandledCatcher();
}
public void handleLoadPackage(final LoadPackageParam lpparam) {
@ -79,6 +81,7 @@ public class MainModule implements IXposedHookZygoteInit, IXposedHookLoadPackage
GlobalActions.setupStatusBar(lpparam);
if (pref_scramblepin) System.ScramblePINHook(lpparam);
if (pref_nopassword) System.NoPasswordHook(lpparam);
}
// if (pkg.equals("com.android.incallui")) {


+ 0
- 114
app/src/main/java/name/mikanoshi/customiuizer/PreferenceFragmentBase.java View File

@ -42,120 +42,6 @@ public class PreferenceFragmentBase extends PreferenceFragment {
((SubFragment)this).finish();
return true;
}
/*
else if (item.getItemId() == R.id.backuprestore) {
final String backupPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/SenseToolbox/";
final String backupFile = "settings_backup";
AlertDialog.Builder alert = new AlertDialog.Builder(act);
alert.setTitle(Helpers.l10n(act, R.string.backup_restore));
alert.setView(Helpers.createCenteredText(act, R.string.backup_restore_choose));
alert.setPositiveButton(Helpers.l10n(act, R.string.do_restore), new DialogInterface.OnClickListener() {
@SuppressWarnings("unchecked")
public void onClick(DialogInterface dialog, int whichButton) {
if (!Helpers.checkStorageReadable(act)) return;
ObjectInputStream input = null;
try {
input = new ObjectInputStream(new FileInputStream(backupPath + backupFile));
Map<String, ?> entries = (Map<String, ?>)input.readObject();
if (entries == null || entries.isEmpty()) throw new Exception("Cannot read entries");
Editor prefEdit = Helpers.prefs.edit();
prefEdit.clear();
for (Entry<String, ?> entry: entries.entrySet()) {
Object val = entry.getValue();
String key = entry.getKey();
if (val instanceof Boolean)
prefEdit.putBoolean(key, ((Boolean)val).booleanValue());
else if (val instanceof Float)
prefEdit.putFloat(key, ((Float)val).floatValue());
else if (val instanceof Integer)
prefEdit.putInt(key, ((Integer)val).intValue());
else if (val instanceof Long)
prefEdit.putLong(key, ((Long)val).longValue());
else if (val instanceof String)
prefEdit.putString(key, ((String)val));
else if (val instanceof Set<?>)
prefEdit.putStringSet(key, ((Set<String>)val));
}
prefEdit.commit();
AlertDialog.Builder alert = new AlertDialog.Builder(act);
alert.setTitle(Helpers.l10n(act, R.string.do_restore));
alert.setView(Helpers.createCenteredText(act, R.string.restore_ok));
alert.setCancelable(false);
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
act.finish();
act.startActivity(act.getIntent());
}
});
alert.show();
} catch (Exception e) {
AlertDialog.Builder alert = new AlertDialog.Builder(act);
alert.setTitle(Helpers.l10n(act, R.string.warning));
alert.setView(Helpers.createCenteredText(act, R.string.storage_cannot_restore));
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {}
});
alert.show();
} finally {
try {
if (input != null) input.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});
alert.setNegativeButton(Helpers.l10n(act, R.string.do_backup), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
if (!Helpers.preparePathForBackup(act, backupPath)) return;
ObjectOutputStream output = null;
try {
output = new ObjectOutputStream(new FileOutputStream(backupPath + backupFile));
output.writeObject(Helpers.prefs.getAll());
AlertDialog.Builder alert = new AlertDialog.Builder(act);
alert.setTitle(Helpers.l10n(act, R.string.do_backup));
alert.setView(Helpers.createCenteredText(act, R.string.backup_ok));
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {}
});
alert.show();
} catch (Exception e) {
AlertDialog.Builder alert = new AlertDialog.Builder(act);
alert.setTitle(Helpers.l10n(act, R.string.warning));
alert.setView(Helpers.createCenteredText(act, R.string.storage_cannot_backup));
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {}
});
alert.show();
e.printStackTrace();
} finally {
try {
if (output != null) {
output.flush();
output.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});
alert.setNeutralButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {}
});
alert.show();
return true;
} else if (item.getItemId() == R.id.about) {
Intent intent = new Intent(act, MAboutScreen.class);
act.startActivity(intent);
}
*/
return super.onOptionsItemSelected(item);
}
/*


+ 5
- 0
app/src/main/java/name/mikanoshi/customiuizer/SharedPrefsProvider.java View File

@ -23,6 +23,7 @@ public class SharedPrefsProvider extends ContentProvider {
static {
uriMatcher.addURI(AUTHORITY, "string/*/*", 1);
uriMatcher.addURI(AUTHORITY, "integer/*/*", 2);
uriMatcher.addURI(AUTHORITY, "boolean/*/*", 3);
}
@Override
@ -48,6 +49,10 @@ public class SharedPrefsProvider extends ContentProvider {
cursor.newRow().add("data", prefs.getInt(parts.get(1), Integer.parseInt(parts.get(2))));
return cursor;
}
case 3: {
cursor.newRow().add("data", prefs.getBoolean(parts.get(1), Integer.parseInt(parts.get(2)) == 1) ? 1 : 0);
return cursor;
}
}
return null;
}


+ 2
- 0
app/src/main/java/name/mikanoshi/customiuizer/SubFragment.java View File

@ -112,6 +112,7 @@ public class SubFragment extends PreferenceFragmentBase {
}
public void saveSharedPrefs() {
if (getView() == null) Log.e("miuizer", "View not yet ready!");
ArrayList<View> nViews = Helpers.getChildViewsRecursive(getView().findViewById(R.id.container), false);
for (View nView : nViews)
if (nView != null) try {
@ -129,6 +130,7 @@ public class SubFragment extends PreferenceFragmentBase {
}
public void loadSharedPrefs() {
if (getView() == null) Log.e("miuizer", "View not yet ready!");
ArrayList<View> nViews = Helpers.getChildViewsRecursive(getView().findViewById(R.id.container), false);
for (View nView : nViews)
if (nView != null) try {


+ 18
- 4
app/src/main/java/name/mikanoshi/customiuizer/SubFragmentWithSearch.java View File

@ -1,22 +1,24 @@
package name.mikanoshi.customiuizer;
import android.annotation.SuppressLint;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.ActionMode;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import miui.view.SearchActionMode;
import name.mikanoshi.customiuizer.utils.AppDataAdapter;
import name.mikanoshi.customiuizer.utils.ResolveInfoAdapter;
public class SubFragmentWithSearch extends SubFragment {
@ -29,6 +31,7 @@ public class SubFragmentWithSearch extends SubFragment {
super.onActivityCreated(savedInstanceState);
getActionBar().setBackgroundDrawable(new ColorDrawable(Color.WHITE));
if (getView() == null) return;
TextView search = getView().findViewById(android.R.id.input);
search.setOnClickListener(new View.OnClickListener() {
@ -37,6 +40,7 @@ public class SubFragmentWithSearch extends SubFragment {
actionMode = startActionMode(new SearchActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
if (getView() == null) return false;
mode.getMenuInflater().inflate(R.menu.menu_mods, menu);
@ -75,8 +79,7 @@ public class SubFragmentWithSearch extends SubFragment {
@Override
public void afterTextChanged(Editable s) {
String filter = s.toString().trim();
((AppDataAdapter)listView.getAdapter()).getFilter().filter(filter);
applyFilter(s.toString().trim());
}
});
return true;
@ -94,7 +97,7 @@ public class SubFragmentWithSearch extends SubFragment {
@Override
public void onDestroyActionMode(ActionMode mode) {
listView.clearTextFilter();
applyFilter("");
getActionBar().show();
actionMode = null;
}
@ -105,6 +108,7 @@ public class SubFragmentWithSearch extends SubFragment {
listView = getView().findViewById(android.R.id.list);
listView.setOnTouchListener(new View.OnTouchListener() {
@Override
@SuppressLint("ClickableViewAccessibility")
public boolean onTouch(View v, MotionEvent event) {
if (actionMode != null && isSearchFocused) {
isSearchFocused = false;
@ -114,4 +118,14 @@ public class SubFragmentWithSearch extends SubFragment {
}
});
}
void applyFilter(String filter) {
if (listView == null) return;
ListAdapter adapter = listView.getAdapter();
if (adapter == null) return;
if (adapter instanceof AppDataAdapter)
((AppDataAdapter)listView.getAdapter()).getFilter().filter(filter);
else if (adapter instanceof ResolveInfoAdapter)
((ResolveInfoAdapter)listView.getAdapter()).getFilter().filter(filter);
}
}

app/src/main/java/name/mikanoshi/customiuizer/CrashReportDialog.java → app/src/main/java/name/mikanoshi/customiuizer/crashreport/Dialog.java View File

@ -1,43 +1,38 @@
package name.mikanoshi.customiuizer;
package name.mikanoshi.customiuizer.crashreport;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import org.acra.ACRA;
import org.acra.ReportField;
import org.acra.config.CoreConfiguration;
import org.acra.data.CrashReportData;
import org.acra.dialog.BaseCrashReportDialog;
import org.acra.file.BulkReportDeleter;
import org.acra.file.CrashReportPersister;
import org.acra.scheduler.SchedulerStarter;
import org.acra.sender.ReportSenderException;
import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
@ -53,14 +48,17 @@ import android.widget.EditText;
import android.widget.FrameLayout.LayoutParams;
import miui.app.AlertDialog;
import name.mikanoshi.customiuizer.ActivityEx;
import name.mikanoshi.customiuizer.R;
import name.mikanoshi.customiuizer.utils.Helpers;
import static org.acra.ACRA.LOG_TAG;
import static org.acra.ReportField.USER_COMMENT;
import static org.acra.ReportField.USER_EMAIL;
public class CrashReportDialog extends BaseCrashReportDialog {
private File mReportFileName;
public class Dialog extends Activity {
private CoreConfiguration config;
private File reportFile;
private String xposedLog;
private EditText desc;
@ -121,13 +119,12 @@ public class CrashReportDialog extends BaseCrashReportDialog {
}
private void sendCrash(final String xposedLogStr) {
String exceptionsPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/CustoMIUIzer/";
CrashReportPersister persister = new CrashReportPersister();
SharedPreferences prefs = getSharedPreferences(Helpers.prefsName, Context.MODE_PRIVATE);
final CrashReportData crashData;
try {
Log.e("crash", mReportFileName.getAbsolutePath());
crashData = persister.load(mReportFileName);
Log.e("crash", reportFile.getAbsolutePath());
crashData = persister.load(reportFile);
crashData.put(USER_COMMENT, desc.getText().toString());
crashData.put(USER_EMAIL, prefs.getString("acra.user.email", ""));
} catch (Throwable t) {
@ -151,7 +148,7 @@ public class CrashReportDialog extends BaseCrashReportDialog {
crashData.put("BUILD", buildData);
StringBuilder sb = new StringBuilder();
try (FileInputStream in = new FileInputStream(new File(exceptionsPath + "uncaught_exceptions"))) {
try (FileInputStream in = new FileInputStream(new File(getFilesDir().getAbsolutePath() + "/uncaught_exceptions"))) {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in))) {
String line;
while ((line = bufferedReader.readLine()) != null) sb.append(line).append("\n");
@ -185,7 +182,7 @@ public class CrashReportDialog extends BaseCrashReportDialog {
@Override
public void run() {
if (finalRes) {
Helpers.emptyFile(exceptionsPath + "uncaught_exceptions", true);
Helpers.emptyFile(getFilesDir().getAbsolutePath() + "/uncaught_exceptions", true);
cancelReports();
showFinishDialog(true, null);
} else {
@ -200,7 +197,7 @@ public class CrashReportDialog extends BaseCrashReportDialog {
try {
String json = report.toJSON();
//final String basicAuth = "Basic " + Base64.encodeToString("Sense6Toolbox:NotASecret".getBytes(), Base64.NO_WRAP);
//final String basicAuth = "Basic " + Base64.encodeToString("login:pass".getBytes(), Base64.NO_WRAP);
URL url = new URL("https://code.highspec.ru/crashreports/reporter.php");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setReadTimeout(10000);
@ -229,7 +226,13 @@ public class CrashReportDialog extends BaseCrashReportDialog {
return false;
}
}
protected final void cancelReports() {
(new Thread(() -> {
(new BulkReportDeleter(this)).deleteReports(false, 0);
})).start();
}
protected void cancelReportsAndFinish() {
cancelReports();
finish();
@ -238,29 +241,35 @@ public class CrashReportDialog extends BaseCrashReportDialog {
int densify(int size) {
return Math.round(getResources().getDisplayMetrics().density * size);
}
@SuppressLint("SetTextI18n")
@Override
protected void preInit(Bundle savedInstanceState) {
try {
setTheme(getResources().getIdentifier("Theme.Light.Settings", "style", "miui"));
getTheme().applyStyle(R.style.ApplyInvisible, true);
} catch (Throwable e) {}
@SuppressLint({"SetTextI18n", "ClickableViewAccessibility"})
protected final void onCreate(Bundle savedInstanceState) {
setTheme(getResources().getIdentifier("Theme.Light.Settings", "style", "miui"));
getTheme().applyStyle(R.style.ApplyInvisible, true);
super.onCreate(savedInstanceState);
if (getIntent().getBooleanExtra("FORCE_CANCEL", false)) {
cancelReportsAndFinish();
return;
}
if (getIntent().getExtras().get("REPORT_FILE") == null) finish();
mReportFileName = (File)getIntent().getExtras().get("REPORT_FILE");
Serializable sConfig = getIntent().getSerializableExtra(DialogInteraction.EXTRA_REPORT_CONFIG);
Serializable sReportFile = getIntent().getSerializableExtra(DialogInteraction.EXTRA_REPORT_FILE);
if (sConfig instanceof CoreConfiguration && sReportFile instanceof File) {
config = (CoreConfiguration) sConfig;
reportFile = (File)sReportFile;
} else {
ACRA.log.w(ACRA.LOG_TAG, "Illegal or incomplete call of CrashReportDialog.");
finish();
}
int title = R.string.warning;
int neutralText = R.string.crash_ignore;
int text = R.string.crash_dialog;
LinearLayout dialogView = new LinearLayout(this);
dialogView.setOrientation(LinearLayout.VERTICAL);
int tries = 5;
xposedLog = null;
while (xposedLog == null && tries > 0) try {
@ -268,10 +277,10 @@ public class CrashReportDialog extends BaseCrashReportDialog {
xposedLog = getXposedLog();
if (xposedLog == null) Thread.sleep(500);
} catch (Throwable e) {}
try {
CrashReportPersister persister = new CrashReportPersister();
CrashReportData crashData = persister.load(mReportFileName);
CrashReportData crashData = persister.load(reportFile);
String payload = crashData.toJSON();
int payloadSize = payload.getBytes(StandardCharsets.UTF_8).length;
boolean isManualReport = crashData.getString(ReportField.STACK_TRACE).contains("Report requested by developer");
@ -290,7 +299,7 @@ public class CrashReportDialog extends BaseCrashReportDialog {
descText.setPadding(0, 0, 0, densify(5));
descText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
descText.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
desc = new EditText(this);
desc.setGravity(Gravity.TOP | Gravity.START);
desc.setInputType(EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE);
@ -302,13 +311,13 @@ public class CrashReportDialog extends BaseCrashReportDialog {
text = R.string.crash_dialog_manual;
neutralText = R.string.cancel;
descText.setText(R.string.crash_dialog_manual_desc);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, densify(80));
lp.setMargins(0, densify(5), 0, densify(10));
desc.setLayoutParams(lp);
} else {
descText.setText(R.string.crash_dialog_manual_desc2);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, densify(60));
lp.setMargins(0, densify(5), 0, densify(10));
desc.setLayoutParams(lp);
@ -333,17 +342,17 @@ public class CrashReportDialog extends BaseCrashReportDialog {
feedbackNote.setPadding(0, 0, 0, 0);
feedbackNote.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
feedbackNote.setText(R.string.crash_dialog_note);
dialogView.addView(mainText);
dialogView.addView(descText);
dialogView.addView(desc);
if (Helpers.prefs.getString("acra.user.email", "").isEmpty())
dialogView.addView(feedbackNote);
if (Helpers.prefs.getString("acra.user.email", null) == null)
dialogView.addView(feedbackNote);
mainText.setText(mainText.getText() + "\n" + getResources().getString(R.string.crash_dialog_manual_size) + ": " + String.valueOf(Math.round(payloadSize / 1024.0f)) + " KB");
} catch (Throwable e) {}
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle(title);
alert.setView(dialogView);
@ -366,9 +375,9 @@ public class CrashReportDialog extends BaseCrashReportDialog {
@Override
public void onClick(View v) {
if (desc != null && desc.getText().toString().trim().equals("")) {
Toast.makeText(CrashReportDialog.this, R.string.crash_needs_desc, Toast.LENGTH_LONG).show();
Toast.makeText(Dialog.this, R.string.crash_needs_desc, Toast.LENGTH_LONG).show();
} else if (!isNetworkAvailable()) {
Toast.makeText(CrashReportDialog.this, R.string.crash_needs_inet, Toast.LENGTH_LONG).show();
Toast.makeText(Dialog.this, R.string.crash_needs_inet, Toast.LENGTH_LONG).show();
} else {
alertDlg.dismiss();
sendCrash(xposedLog);
@ -376,4 +385,8 @@ public class CrashReportDialog extends BaseCrashReportDialog {
}
});
}
protected final CoreConfiguration getConfig() {
return config;
}
}

+ 43
- 0
app/src/main/java/name/mikanoshi/customiuizer/crashreport/DialogInteraction.java View File

@ -0,0 +1,43 @@
package name.mikanoshi.customiuizer.crashreport;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import org.acra.ACRA;
import org.acra.config.CoreConfiguration;
import org.acra.interaction.ReportInteraction;
import org.acra.prefs.SharedPreferencesFactory;
import java.io.File;
import static org.acra.ACRA.LOG_TAG;
public class DialogInteraction implements ReportInteraction {
static final String EXTRA_REPORT_FILE = "REPORT_FILE";
static final String EXTRA_REPORT_CONFIG = "REPORT_CONFIG";
public DialogInteraction() {
super();
}
@Override
public boolean performInteraction(Context context, CoreConfiguration config, File reportFile) {
final SharedPreferences prefs = new SharedPreferencesFactory(context, config).create();
if (prefs.getBoolean(ACRA.PREF_ALWAYS_ACCEPT, false)) return true;
<