Files
status-react/android/app/src/main/java/im/status/ethereum/MainActivity.java
T

261 lines
11 KiB
Java
Raw Normal View History

2016-11-18 16:49:51 +02:00
package im.status.ethereum;
2016-03-23 16:48:26 +02:00
import android.content.Context;
2018-03-14 12:49:41 +03:00
import android.annotation.TargetApi;
2019-08-07 15:08:22 +02:00
import androidx.annotation.Nullable;
2016-06-08 12:43:02 +02:00
import android.app.AlertDialog;
import android.app.ActivityManager;
2016-06-08 12:43:02 +02:00
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Looper;
import android.preference.PreferenceManager;
2019-08-07 15:08:22 +02:00
import androidx.core.app.ActivityCompat;
import android.util.Log;
import android.view.WindowManager;
2016-06-16 07:23:11 +03:00
import android.content.Intent;
import android.content.SharedPreferences;
2016-06-21 12:03:39 +03:00
import android.content.res.Configuration;
import android.provider.Settings;
import android.os.Bundle;
import android.os.Handler;
2019-06-12 09:25:18 +03:00
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
2019-06-12 09:25:18 +03:00
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
2019-06-20 19:14:56 +03:00
import com.facebook.react.ReactFragmentActivity;
2021-05-24 16:25:05 +02:00
import com.reactnativenavigation.NavigationActivity;
2018-03-14 12:49:41 +03:00
import com.facebook.react.modules.core.PermissionListener;
import androidx.core.splashscreen.SplashScreen;
2016-06-01 11:41:50 +03:00
import java.util.Properties;
import im.status.ethereum.module.StatusThreadPoolExecutor;
import im.status.ethereum.MainApplication;
2016-07-18 19:29:51 +03:00
2021-05-24 16:25:05 +02:00
public class MainActivity extends NavigationActivity
implements ActivityCompat.OnRequestPermissionsResultCallback{
2018-03-14 12:49:41 +03:00
@Nullable private PermissionListener mPermissionListener;
private boolean keepSplash = true;
private final int SPLASH_DELAY = 3200;
2018-03-14 12:49:41 +03:00
private static void registerUncaughtExceptionHandler(final Context context) {
final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread thread, final Throwable t) {
// High priority, so don't use StatusThreadPoolExecutor
new Thread() {
@Override
public void run() {
Looper.prepare();
new AlertDialog.Builder(context)
.setTitle("Error")
.setMessage(t.toString())
.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, final int id) {
dialog.dismiss();
defaultUncaughtExceptionHandler.uncaughtException(thread, t);
}
}).show();
Looper.loop();
}
}.start();
}
});
}
private ActivityManager getActivityManager() {
return (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
}
private ActivityManager.MemoryInfo getAvailableMemory(final ActivityManager activityManager) {
final ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo;
}
2016-09-07 20:35:04 +03:00
protected void configureStatus() {
2016-06-08 12:43:02 +02:00
// Required because of crazy APN settings redirecting localhost (found in GB)
2016-03-23 17:02:53 +02:00
Properties properties = System.getProperties();
properties.setProperty("http.nonProxyHosts", "localhost|127.0.0.1");
properties.setProperty("https.nonProxyHosts", "localhost|127.0.0.1");
}
private Intent createNotificationSettingsIntent() {
final Intent intent = new Intent();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
2018-03-29 15:48:20 +01:00
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
} else {
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + getPackageName()));
}
return intent;
}
private void tryToEmit(String eventName, WritableMap event) {
try {
((MainApplication) getApplication()).getReactNativeHost()
.getReactInstanceManager()
.getCurrentReactContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("url", event);
} catch(Exception e) {/* we expect NPE on first start, which is OK because we have a fallback */}
}
@Override
public void onNewIntent(final Intent intent) {
2018-06-27 15:09:48 +02:00
super.onNewIntent(intent);
2018-03-27 06:20:29 +01:00
if (intent.getDataString() != null && intent.getData().getScheme().startsWith("app-settings")) {
startActivity(createNotificationSettingsIntent());
}
}
2016-06-08 12:43:02 +02:00
@Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen splashScreen = SplashScreen.installSplashScreen(this);
setTheme(R.style.DarkTheme);
// Make sure we get an Alert for every uncaught exceptions
registerUncaughtExceptionHandler(MainActivity.this);
// Report memory details for this application
final ActivityManager activityManager = getActivityManager();
Log.v("RNBootstrap", "Available system memory "+getAvailableMemory(activityManager).availMem + ", maximum usable application memory " + activityManager.getLargeMemoryClass()+"M");
setSecureFlag();
2020-03-17 12:15:02 +03:00
// NOTE: Try to not restore the state https://github.com/software-mansion/react-native-screens/issues/17
super.onCreate(null);
2017-08-09 18:30:08 +03:00
if (!shouldShowRootedNotification()) {
2016-09-07 20:35:04 +03:00
configureStatus();
2016-06-08 12:43:02 +02:00
} else {
AlertDialog dialog = new AlertDialog.Builder(MainActivity.this)
.setMessage(getResources().getString(R.string.root_warning))
2016-06-08 12:43:02 +02:00
.setPositiveButton(getResources().getString(R.string.root_okay), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
rejectRootedNotification();
2016-06-08 12:43:02 +02:00
dialog.dismiss();
2016-09-07 20:35:04 +03:00
configureStatus();
2016-06-08 12:43:02 +02:00
}
})
.setNegativeButton(getResources().getString(R.string.root_cancel), new OnClickListener() {
2016-06-08 12:43:02 +02:00
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
MainActivity.this.finishAffinity();
}
})
.setOnCancelListener(new OnCancelListener() {
2016-06-08 12:43:02 +02:00
@Override
public void onCancel(DialogInterface dialog) {
dialog.dismiss();
MainActivity.this.finishAffinity();
}
})
.create();
2016-06-08 12:43:02 +02:00
dialog.show();
}
2017-10-12 21:49:48 +02:00
Runnable r = new Runnable() {
2017-10-12 21:49:48 +02:00
@Override
public void run() {
System.loadLibrary("status-logs");
// when app is started but the Activity has been destroyed, the deep linking url event is
// not emitted when coming back to foreground. This is a workaround. If the problem is
// resolved in react-native this code should be removed
if (getIntent().getData() != null) {
WritableMap event = Arguments.createMap();
event.putString("url", getIntent().getDataString());
// on first start emit will (silently) fail, but the regular deep linking handler will work
tryToEmit("url", event);
}
2017-10-12 21:49:48 +02:00
}
};
splashScreen.setKeepOnScreenCondition(() -> keepSplash);
Handler handler = new Handler();
handler.postDelayed(() -> keepSplash = false, SPLASH_DELAY);
StatusThreadPoolExecutor.getInstance().execute(r);
2016-03-23 17:02:53 +02:00
}
2016-06-16 07:23:11 +03:00
@Override
protected void onDestroy() {
super.onDestroy();
}
2016-03-23 16:48:26 +02:00
2016-06-21 12:03:39 +03:00
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Intent intent = new Intent("onConfigurationChanged");
intent.putExtra("newConfig", newConfig);
this.sendBroadcast(intent);
}
private static final String REJECTED_ROOTED_NOTIFICATION = "rejectedRootedNotification";
private static final Integer FREQUENCY_OF_REMINDER_IN_PERCENT = 5;
private boolean shouldShowRootedNotification() {
2020-05-19 13:40:39 +03:00
if (RootUtil.isDeviceRooted() && BuildConfig.ENABLE_ROOT_ALERT == "1") {
if (userRejectedRootedNotification()) {
return ((Math.random() * 100) < FREQUENCY_OF_REMINDER_IN_PERCENT);
} else return true;
} else {
return false;
}
}
private boolean userRejectedRootedNotification() {
SharedPreferences preferences = getPreferences(0);
return preferences.getBoolean(REJECTED_ROOTED_NOTIFICATION, false);
}
private void rejectRootedNotification() {
SharedPreferences preferences = getPreferences(0);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(REJECTED_ROOTED_NOTIFICATION, true);
editor.commit();
}
private void setSecureFlag() {
final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
final boolean setSecure = sharedPrefs.getBoolean("BLANK_PREVIEW", false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && setSecure) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
2018-03-14 12:49:41 +03:00
@TargetApi(Build.VERSION_CODES.M)
public void requestPermissions(String[] permissions, int requestCode, PermissionListener listener) {
mPermissionListener = listener;
requestPermissions(permissions, requestCode);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
2018-03-14 12:49:41 +03:00
if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener = null;
}
}
2016-03-23 16:48:26 +02:00
}