Skip to content

Commit

Permalink
Improve error reports
Browse files Browse the repository at this point in the history
  • Loading branch information
woesss committed Aug 23, 2024
1 parent a222d4a commit 3cc10ae
Show file tree
Hide file tree
Showing 16 changed files with 372 additions and 245 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ captures/
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
.cxx/

/.kotlin/
41 changes: 15 additions & 26 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,25 @@ android {
versionCode = 48
versionName = "0.87.1"
resValue("string", "app_name", rootProject.name)
resValue("string", "app_center", secret.getProperty("appCenterKey", ""))
vectorDrawables.useSupportLibrary = true
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

androidResources {
generateLocaleConfig = true
}
androidResources.generateLocaleConfig = true

buildFeatures {
viewBinding = true
prefab = true
buildConfig = true
}

signingConfigs {
create("emulator") {
if (secret.isNotEmpty()) {
keyAlias = secret.getProperty("keyAlias")
keyPassword = secret.getProperty("keyPassword")
storeFile = rootProject.file(secret.getProperty("storeFile"))
storePassword = secret.getProperty("storePassword")
}
signingConfigs.create("emulator") {
if (secret.isNotEmpty()) {
keyAlias = secret.getProperty("keyAlias")
keyPassword = secret.getProperty("keyPassword")
storeFile = rootProject.file(secret.getProperty("storeFile"))
storePassword = secret.getProperty("storePassword")
}
}

Expand All @@ -62,9 +59,7 @@ android {
}
}

lint {
disable += "MissingTranslation"
}
lint.disable += "MissingTranslation"

flavorDimensions += "default"
productFlavors {
Expand Down Expand Up @@ -94,20 +89,14 @@ android {
}
}

splits {
abi {
isEnable = true
reset()
include("x86", "armeabi-v7a", "x86_64", "arm64-v8a")
isUniversalApk = true
}
splits.abi {
isEnable = true
reset()
include("x86", "armeabi-v7a", "x86_64", "arm64-v8a")
isUniversalApk = true
}

externalNativeBuild {
ndkBuild {
path("src/main/cpp/Android.mk")
}
}
externalNativeBuild.ndkBuild.path("src/main/cpp/Android.mk")

compileOptions {
targetCompatibility = JavaVersion.VERSION_17
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@
android:theme="@style/FilePickerTheme" />
<activity android:name=".config.ProfilesActivity" android:exported="false" />
<activity android:name="com.nokia.mid.ui.NotificationActivity" />
<activity
android:name="ru.playsoftware.j2meloader.crashes.dialog.CrashReportDialog"
android:theme="@style/Theme.AppCompat.DayNight.Dialog.Alert"
android:excludeFromRecents="true"
android:finishOnTaskLaunch="true"
android:launchMode="singleInstance"
android:process=":acra" />

<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright 2017-2018 Nikita Shakarun
* Copyright 2020-2024 Yury Kharchenko
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,44 +17,28 @@

package ru.playsoftware.j2meloader;

import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Build;
import android.view.ViewConfiguration;

import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.multidex.MultiDex;
import androidx.preference.PreferenceManager;

import org.acra.ACRA;
import org.acra.config.CoreConfigurationBuilder;
import org.acra.config.DialogConfigurationBuilder;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import ru.playsoftware.j2meloader.crashes.AppCenterCollector;
import ru.playsoftware.j2meloader.util.Constants;
import ru.playsoftware.j2meloader.util.FileUtils;

public class EmulatorApplication extends Application {
private static final byte[] SIGNATURE_SHA = {
125, 47, 64, 33, 91, -86, -121, 89, 11, 24, -118, -93, 35, 53, -34, -114, -119, -60, -48, 55
};

public class EmulatorApplication extends Application implements OnSharedPreferenceChangeListener {
private static EmulatorApplication instance;

@Keep
private final SharedPreferences.OnSharedPreferenceChangeListener themeListener = (sharedPreferences, key) -> {
if (Constants.PREF_THEME.equals(key)) {
setNightMode(sharedPreferences.getString(Constants.PREF_THEME, null));
}
};
public static EmulatorApplication getInstance() {
return instance;
}
Expand All @@ -67,20 +52,15 @@ protected void attachBaseContext(Context base) {
}

ACRA.init(this, new CoreConfigurationBuilder()
.withBuildConfigClass(BuildConfig.class)
.withParallel(false)
.withSendReportsInDevMode(false)
.withPluginConfigurations(new DialogConfigurationBuilder()
.withTitle(getString(R.string.crash_dialog_title))
.withText(getString(R.string.crash_dialog_message))
.withPositiveButtonText(getString(R.string.report_crash))
.withResTheme(androidx.appcompat.R.style.Theme_AppCompat_DayNight_Dialog)
.withEnabled(true)
.build()
));
ACRA.getErrorReporter().setEnabled(isSignatureValid());
.withReportContent(AppCenterCollector.REPORT_FIELDS));

SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
sp.registerOnSharedPreferenceChangeListener(themeListener);
if (!sp.contains(Constants.PREF_TOOLBAR)) {
boolean enable = !ViewConfiguration.get(this).hasPermanentMenuKey();
sp.edit().putBoolean(Constants.PREF_TOOLBAR, enable).apply();
}
sp.registerOnSharedPreferenceChangeListener(this);
setNightMode(sp.getString(Constants.PREF_THEME, null));
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
Expand All @@ -94,34 +74,6 @@ public static String getProcessName() {
}
}

@SuppressLint("PackageManagerGetSignatures")
private boolean isSignatureValid() {
try {
Signature[] signatures;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
PackageInfo info = getPackageManager()
.getPackageInfo(getPackageName(), PackageManager.GET_SIGNING_CERTIFICATES);
signatures = info.signingInfo.getApkContentsSigners();
} else {
PackageInfo info = getPackageManager()
.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
signatures = info.signatures;
}
MessageDigest md = MessageDigest.getInstance("SHA-1");
for (Signature signature : signatures) {
md.update(signature.toByteArray());
if (MessageDigest.isEqual(SIGNATURE_SHA, md.digest())) {
return true;
}
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return false;
}

void setNightMode(String theme) {
if (theme == null) {
theme = getString(R.string.pref_theme_default);
Expand All @@ -135,4 +87,11 @@ void setNightMode(String theme) {
default -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
});
}

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (Constants.PREF_THEME.equals(key)) {
setNightMode(sharedPreferences.getString(Constants.PREF_THEME, null));
}
}
}
38 changes: 4 additions & 34 deletions app/src/main/java/ru/playsoftware/j2meloader/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,15 @@

package ru.playsoftware.j2meloader;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.ViewConfiguration;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.ViewModelProvider;
import androidx.preference.PreferenceManager;

Expand All @@ -44,7 +37,6 @@
import ru.playsoftware.j2meloader.config.Config;
import ru.playsoftware.j2meloader.util.Constants;
import ru.playsoftware.j2meloader.util.FileUtils;
import ru.playsoftware.j2meloader.util.LogUtils;
import ru.playsoftware.j2meloader.util.PickDirResultContract;
import ru.playsoftware.j2meloader.util.StoragePermissionHelper;
import ru.woesss.j2me.installer.InstallerDialog;
Expand All @@ -58,7 +50,6 @@ public class MainActivity extends AppCompatActivity {
this::onPickDirResult
);

private SharedPreferences preferences;
private AppListModel appListModel;

@Override
Expand All @@ -67,7 +58,6 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
storagePermissionHelper.launch(this);
appListModel = new ViewModelProvider(this).get(AppListModel.class);
appListModel.getErrors().observe(this, this::alertDbError);
if (savedInstanceState == null) {
Intent intent = getIntent();
Uri uri = null;
Expand All @@ -78,11 +68,6 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fragment).commit();
}
preferences = PreferenceManager.getDefaultSharedPreferences(this);
if (!preferences.contains(Constants.PREF_TOOLBAR)) {
boolean enable = !ViewConfiguration.get(this).hasPermanentMenuKey();
preferences.edit().putBoolean(Constants.PREF_TOOLBAR, enable).apply();
}
setVolumeControlStream(AudioManager.STREAM_MUSIC);
}

Expand Down Expand Up @@ -154,7 +139,10 @@ private void applyWorkDir(File file) {
alertDirCannotCreate(path);
return;
}
preferences.edit().putString(Constants.PREF_EMULATOR_DIR, path).apply();
PreferenceManager.getDefaultSharedPreferences(this)
.edit()
.putString(Constants.PREF_EMULATOR_DIR, path)
.apply();
}

@Override
Expand All @@ -165,22 +153,4 @@ protected void onNewIntent(Intent intent) {
InstallerDialog.newInstance(uri).show(getSupportFragmentManager(), "installer");
}
}

private void alertDbError(Throwable throwable) {
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle(R.string.error)
.setMessage(LogUtils.getPrettyText(throwable))
.setPositiveButton(android.R.string.ok, null);
ClipboardManager cm = ContextCompat.getSystemService(this, ClipboardManager.class);
if (cm != null) {
builder.setNeutralButton(android.R.string.copy, (d, w) -> {
Context context = ((AlertDialog) d).getContext();
cm.setPrimaryClip(new ClipData(context.getString(R.string.app_name) + " stacktrace",
new String[]{"text/plain"},
new ClipData.Item(LogUtils.getStackTraceString(throwable))));
Toast.makeText(context, R.string.msg_text_copied_to_clipboard, Toast.LENGTH_SHORT).show();
});
}
builder.show();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import android.content.SharedPreferences;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModel;
import androidx.preference.PreferenceManager;

Expand Down Expand Up @@ -50,14 +50,10 @@ public void setEmulatorDirectory(String emulatorDir) {
appRepository.setDatabaseFile(emulatorDir + Config.APPS_DB_NAME);
}

MutableLiveData<List<AppItem>> getAppList() {
LiveData<List<AppItem>> getAppList() {
return appRepository.getAppList();
}

public MutableLiveData<Throwable> getErrors() {
return appRepository.getErrors();
}

void updateApp(AppItem item) {
appRepository.update(item);
}
Expand Down Expand Up @@ -93,7 +89,7 @@ public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
} else if (PREF_EMULATOR_DIR.equals(key)) {
String path = sp.getString(key, null);
if (path != null) {
appRepository.setDatabaseFile(path + Config.APPS_DB_NAME);
setEmulatorDirectory(path);
}
}
}
Expand Down
Loading

0 comments on commit 3cc10ae

Please sign in to comment.