Fixed problem with Android 8 permissions. Needed to implement a new unhandled Exception Handler because mine kept giving Permission Denied errors.
This commit is contained in:
@@ -41,6 +41,7 @@ dependencies {
|
|||||||
implementation 'com.google.android.gms:play-services:10.0.1'
|
implementation 'com.google.android.gms:play-services:10.0.1'
|
||||||
implementation 'com.github.wendykierp:JTransforms:3.0'
|
implementation 'com.github.wendykierp:JTransforms:3.0'
|
||||||
implementation 'com.google.android.gms:play-services-location:10.0.0'
|
implementation 'com.google.android.gms:play-services-location:10.0.0'
|
||||||
|
//implementation 'com.github.RohitSurwase.UCE-Handler:uce_handler:1.3'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,9 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".PrefActivity"
|
android:name=".PrefActivity"
|
||||||
android:label="OpenSeizureDetector Preferences"></activity>
|
android:label="OpenSeizureDetector Preferences"></activity>
|
||||||
|
<activity
|
||||||
|
android:name="com.rohitss.uceh.UCEDefaultActivity"
|
||||||
|
android:process=":error_activity"></activity>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".SdServer"
|
android:name=".SdServer"
|
||||||
|
|||||||
332
app/src/main/java/com/rohitss/uceh/UCEDefaultActivity.java
Normal file
332
app/src/main/java/com/rohitss/uceh/UCEDefaultActivity.java
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * Copyright © 2018 Rohit Sahebrao Surwase.
|
||||||
|
* *
|
||||||
|
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* * you may not use this file except in compliance with the License.
|
||||||
|
* * You may obtain a copy of the License at
|
||||||
|
* *
|
||||||
|
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* *
|
||||||
|
* * Unless required by applicable law or agreed to in writing, software
|
||||||
|
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* * See the License for the specific language governing permissions and
|
||||||
|
* * limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.rohitss.uceh;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.ClipData;
|
||||||
|
import android.content.ClipboardManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import uk.org.openseizuredetector.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <b></b>
|
||||||
|
* <p>This class is used to </p>
|
||||||
|
* Created by Rohit.
|
||||||
|
*/
|
||||||
|
public final class UCEDefaultActivity extends Activity {
|
||||||
|
private File txtFile;
|
||||||
|
private String strCurrentErrorLog;
|
||||||
|
private String TAG = "UCEDefaultActivity";
|
||||||
|
|
||||||
|
@SuppressLint("PrivateResource")
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
setTheme(android.R.style.Theme_Holo_Light_DarkActionBar);
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
Log.i(TAG,"onCreate()");
|
||||||
|
setContentView(R.layout.default_error_activity);
|
||||||
|
findViewById(R.id.button_close_app).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
UCEHandler.closeApplication(UCEDefaultActivity.this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
findViewById(R.id.button_copy_error_log).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
copyErrorToClipboard();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
findViewById(R.id.button_share_error_log).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
shareErrorLog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
findViewById(R.id.button_save_error_log).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
saveErrorLogToFile(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
findViewById(R.id.button_email_error_log).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
emailErrorLog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
findViewById(R.id.button_view_error_log).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
AlertDialog dialog = new AlertDialog.Builder(UCEDefaultActivity.this)
|
||||||
|
.setTitle("Error Log")
|
||||||
|
.setMessage(getAllErrorDetailsFromIntent(UCEDefaultActivity.this, getIntent()))
|
||||||
|
.setPositiveButton("Copy Log & Close",
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
copyErrorToClipboard();
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNeutralButton("Close",
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
TextView textView = dialog.findViewById(android.R.id.message);
|
||||||
|
if (textView != null) {
|
||||||
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApplicationName(Context context) {
|
||||||
|
ApplicationInfo applicationInfo = context.getApplicationInfo();
|
||||||
|
int stringId = applicationInfo.labelRes;
|
||||||
|
return stringId == 0 ? applicationInfo.nonLocalizedLabel.toString() : context.getString(stringId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getVersionName(Context context) {
|
||||||
|
try {
|
||||||
|
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
|
||||||
|
return packageInfo.versionName;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getActivityLogFromIntent(Intent intent) {
|
||||||
|
return intent.getStringExtra(UCEHandler.EXTRA_ACTIVITY_LOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getStackTraceFromIntent(Intent intent) {
|
||||||
|
return intent.getStringExtra(UCEHandler.EXTRA_STACK_TRACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getEmailAddressesFromIntent(Intent intent) {
|
||||||
|
Log.d(TAG,"getEmailFromIntent - "+intent.getStringExtra(UCEHandler.EXTRA_EMAIL_ADDRESSES)+".");
|
||||||
|
return intent.getStringExtra(UCEHandler.EXTRA_EMAIL_ADDRESSES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void emailErrorLog() {
|
||||||
|
saveErrorLogToFile(false);
|
||||||
|
String errorLog = getAllErrorDetailsFromIntent(UCEDefaultActivity.this, getIntent());
|
||||||
|
Log.d(TAG,"emailErrorLog() - addresses = "+UCEHandler.COMMA_SEPARATED_EMAIL_ADDRESSES+".");
|
||||||
|
//String[] emailAddressArray = UCEHandler.COMMA_SEPARATED_EMAIL_ADDRESSES.trim().split("\\s*,\\s*");
|
||||||
|
String emailStr = getEmailAddressesFromIntent(getIntent());
|
||||||
|
Log.d(TAG,"emailErrorLog() - EmailStr = "+emailStr);
|
||||||
|
String[] emailAddressArray = emailStr.split("\\s*,\\s*");
|
||||||
|
//String[] emailAddressArray = {"crashreports@openseizuredetector.org.uk"};
|
||||||
|
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
|
||||||
|
emailIntent.setType("plain/text");
|
||||||
|
emailIntent.putExtra(Intent.EXTRA_EMAIL, emailAddressArray);
|
||||||
|
emailIntent.putExtra(Intent.EXTRA_SUBJECT, getApplicationName(UCEDefaultActivity.this) + " Application Crash Error Log");
|
||||||
|
emailIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.email_welcome_note) + errorLog);
|
||||||
|
//if (txtFile.exists()) {
|
||||||
|
// Uri filePath = Uri.fromFile(txtFile);
|
||||||
|
// emailIntent.putExtra(Intent.EXTRA_STREAM, filePath);
|
||||||
|
//}
|
||||||
|
startActivity(Intent.createChooser(emailIntent, "Email Error Log"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveErrorLogToFile(boolean isShowToast) {
|
||||||
|
Boolean isSDPresent = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
|
||||||
|
if (isSDPresent && isExternalStorageWritable()) {
|
||||||
|
Date currentDate = new Date();
|
||||||
|
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
|
||||||
|
String strCurrentDate = dateFormat.format(currentDate);
|
||||||
|
strCurrentDate = strCurrentDate.replace(" ", "_");
|
||||||
|
String errorLogFileName = getApplicationName(UCEDefaultActivity.this) + "_Error-Log_" + strCurrentDate;
|
||||||
|
String errorLog = getAllErrorDetailsFromIntent(UCEDefaultActivity.this, getIntent());
|
||||||
|
String fullPath = Environment.getExternalStorageDirectory() + "/AppErrorLogs_UCEH/";
|
||||||
|
FileOutputStream outputStream;
|
||||||
|
try {
|
||||||
|
File file = new File(fullPath);
|
||||||
|
file.mkdir();
|
||||||
|
txtFile = new File(fullPath + errorLogFileName + ".txt");
|
||||||
|
txtFile.createNewFile();
|
||||||
|
outputStream = new FileOutputStream(txtFile);
|
||||||
|
outputStream.write(errorLog.getBytes());
|
||||||
|
outputStream.close();
|
||||||
|
if (txtFile.exists() && isShowToast) {
|
||||||
|
Toast.makeText(this, "File Saved Successfully", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e("REQUIRED", "This app does not have write storage permission to save log file.");
|
||||||
|
if (isShowToast) {
|
||||||
|
Toast.makeText(this, "Storage Permission Not Found", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void shareErrorLog() {
|
||||||
|
String errorLog = getAllErrorDetailsFromIntent(UCEDefaultActivity.this, getIntent());
|
||||||
|
Intent share = new Intent(Intent.ACTION_SEND);
|
||||||
|
share.setType("text/plain");
|
||||||
|
share.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
|
||||||
|
share.putExtra(Intent.EXTRA_SUBJECT, "Application Crash Error Log");
|
||||||
|
share.putExtra(Intent.EXTRA_TEXT, errorLog);
|
||||||
|
startActivity(Intent.createChooser(share, "Share Error Log"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyErrorToClipboard() {
|
||||||
|
String errorInformation = getAllErrorDetailsFromIntent(UCEDefaultActivity.this, getIntent());
|
||||||
|
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||||
|
if (clipboard != null) {
|
||||||
|
ClipData clip = ClipData.newPlainText("View Error Log", errorInformation);
|
||||||
|
clipboard.setPrimaryClip(clip);
|
||||||
|
Toast.makeText(UCEDefaultActivity.this, "Error Log Copied", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getAllErrorDetailsFromIntent(Context context, Intent intent) {
|
||||||
|
if (TextUtils.isEmpty(strCurrentErrorLog)) {
|
||||||
|
String LINE_SEPARATOR = "\n";
|
||||||
|
StringBuilder errorReport = new StringBuilder();
|
||||||
|
errorReport.append("***** UCE HANDLER Library ");
|
||||||
|
errorReport.append("\n***** by Rohit Surwase \n");
|
||||||
|
errorReport.append("\n***** DEVICE INFO \n");
|
||||||
|
errorReport.append("Brand: ");
|
||||||
|
errorReport.append(Build.BRAND);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
errorReport.append("Device: ");
|
||||||
|
errorReport.append(Build.DEVICE);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
errorReport.append("Model: ");
|
||||||
|
errorReport.append(Build.MODEL);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
errorReport.append("Manufacturer: ");
|
||||||
|
errorReport.append(Build.MANUFACTURER);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
errorReport.append("Product: ");
|
||||||
|
errorReport.append(Build.PRODUCT);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
errorReport.append("SDK: ");
|
||||||
|
errorReport.append(Build.VERSION.SDK);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
errorReport.append("Release: ");
|
||||||
|
errorReport.append(Build.VERSION.RELEASE);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
errorReport.append("\n***** APP INFO \n");
|
||||||
|
String versionName = getVersionName(context);
|
||||||
|
errorReport.append("Version: ");
|
||||||
|
errorReport.append(versionName);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
Date currentDate = new Date();
|
||||||
|
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
|
||||||
|
String firstInstallTime = getFirstInstallTimeAsString(context, dateFormat);
|
||||||
|
if (!TextUtils.isEmpty(firstInstallTime)) {
|
||||||
|
errorReport.append("Installed On: ");
|
||||||
|
errorReport.append(firstInstallTime);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
}
|
||||||
|
String lastUpdateTime = getLastUpdateTimeAsString(context, dateFormat);
|
||||||
|
if (!TextUtils.isEmpty(lastUpdateTime)) {
|
||||||
|
errorReport.append("Updated On: ");
|
||||||
|
errorReport.append(lastUpdateTime);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
}
|
||||||
|
errorReport.append("Current Date: ");
|
||||||
|
errorReport.append(dateFormat.format(currentDate));
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
errorReport.append("\n***** ERROR LOG \n");
|
||||||
|
errorReport.append(getStackTraceFromIntent(intent));
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
String activityLog = getActivityLogFromIntent(intent);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
if (activityLog != null) {
|
||||||
|
errorReport.append("\n***** USER ACTIVITIES \n");
|
||||||
|
errorReport.append("User Activities: ");
|
||||||
|
errorReport.append(activityLog);
|
||||||
|
errorReport.append(LINE_SEPARATOR);
|
||||||
|
}
|
||||||
|
errorReport.append("\n***** END OF LOG *****\n");
|
||||||
|
strCurrentErrorLog = errorReport.toString();
|
||||||
|
return strCurrentErrorLog;
|
||||||
|
} else {
|
||||||
|
return strCurrentErrorLog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFirstInstallTimeAsString(Context context, DateFormat dateFormat) {
|
||||||
|
long firstInstallTime;
|
||||||
|
try {
|
||||||
|
firstInstallTime = context
|
||||||
|
.getPackageManager()
|
||||||
|
.getPackageInfo(context.getPackageName(), 0)
|
||||||
|
.firstInstallTime;
|
||||||
|
return dateFormat.format(new Date(firstInstallTime));
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getLastUpdateTimeAsString(Context context, DateFormat dateFormat) {
|
||||||
|
long lastUpdateTime;
|
||||||
|
try {
|
||||||
|
lastUpdateTime = context
|
||||||
|
.getPackageManager()
|
||||||
|
.getPackageInfo(context.getPackageName(), 0)
|
||||||
|
.lastUpdateTime;
|
||||||
|
return dateFormat.format(new Date(lastUpdateTime));
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExternalStorageWritable() {
|
||||||
|
String state = Environment.getExternalStorageState();
|
||||||
|
if (Environment.MEDIA_MOUNTED.equals(state)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
271
app/src/main/java/com/rohitss/uceh/UCEHandler.java
Normal file
271
app/src/main/java/com/rohitss/uceh/UCEHandler.java
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * Copyright © 2018 Rohit Sahebrao Surwase.
|
||||||
|
* *
|
||||||
|
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* * you may not use this file except in compliance with the License.
|
||||||
|
* * You may obtain a copy of the License at
|
||||||
|
* *
|
||||||
|
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* *
|
||||||
|
* * Unless required by applicable law or agreed to in writing, software
|
||||||
|
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* * See the License for the specific language governing permissions and
|
||||||
|
* * limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.rohitss.uceh;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <b></b>
|
||||||
|
* <p>This class is used to </p>
|
||||||
|
* Created by Rohit.
|
||||||
|
*/
|
||||||
|
public final class UCEHandler {
|
||||||
|
static final String EXTRA_STACK_TRACE = "EXTRA_STACK_TRACE";
|
||||||
|
static final String EXTRA_ACTIVITY_LOG = "EXTRA_ACTIVITY_LOG";
|
||||||
|
static final String EXTRA_EMAIL_ADDRESSES = "EXTRA_EMAIL_ADDRESSES";
|
||||||
|
private final static String TAG = "UCEHandler";
|
||||||
|
private static final String UCE_HANDLER_PACKAGE_NAME = "com.rohitss.uceh";
|
||||||
|
private static final String DEFAULT_HANDLER_PACKAGE_NAME = "com.android.internal.os";
|
||||||
|
private static final int MAX_STACK_TRACE_SIZE = 131071; //128 KB - 1
|
||||||
|
private static final int MAX_ACTIVITIES_IN_LOG = 50;
|
||||||
|
private static final String SHARED_PREFERENCES_FILE = "uceh_preferences";
|
||||||
|
private static final String SHARED_PREFERENCES_FIELD_TIMESTAMP = "last_crash_timestamp";
|
||||||
|
private static final Deque<String> activityLog = new ArrayDeque<>(MAX_ACTIVITIES_IN_LOG);
|
||||||
|
static String COMMA_SEPARATED_EMAIL_ADDRESSES;
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
|
private static Application application;
|
||||||
|
private static boolean isInBackground = true;
|
||||||
|
private static boolean isBackgroundMode;
|
||||||
|
private static boolean isUCEHEnabled;
|
||||||
|
private static boolean isTrackActivitiesEnabled;
|
||||||
|
private static WeakReference<Activity> lastActivityCreated = new WeakReference<>(null);
|
||||||
|
|
||||||
|
UCEHandler(Builder builder) {
|
||||||
|
isUCEHEnabled = builder.isUCEHEnabled;
|
||||||
|
isTrackActivitiesEnabled = builder.isTrackActivitiesEnabled;
|
||||||
|
isBackgroundMode = builder.isBackgroundModeEnabled;
|
||||||
|
COMMA_SEPARATED_EMAIL_ADDRESSES = builder.commaSeparatedEmailAddresses;
|
||||||
|
Log.d(TAG,"UCEHandler() - Email Addresses = "+COMMA_SEPARATED_EMAIL_ADDRESSES+".");
|
||||||
|
Log.d(TAG,"UCEHandler() - UCEHandler.Email Addresses = "+UCEHandler.COMMA_SEPARATED_EMAIL_ADDRESSES+".");
|
||||||
|
setUCEHandler(builder.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setUCEHandler(final Context context) {
|
||||||
|
Log.i(TAG,"setUCEHandler() - email addresses = "+UCEHandler.COMMA_SEPARATED_EMAIL_ADDRESSES+".");
|
||||||
|
try {
|
||||||
|
if (context != null) {
|
||||||
|
final Thread.UncaughtExceptionHandler oldHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
|
if (oldHandler != null && oldHandler.getClass().getName().startsWith(UCE_HANDLER_PACKAGE_NAME)) {
|
||||||
|
Log.e(TAG, "UCEHandler was already installed, doing nothing!");
|
||||||
|
} else {
|
||||||
|
if (oldHandler != null && !oldHandler.getClass().getName().startsWith(DEFAULT_HANDLER_PACKAGE_NAME)) {
|
||||||
|
Log.e(TAG, "You already have an UncaughtExceptionHandler. If you use a custom UncaughtExceptionHandler, it should be initialized after UCEHandler! Installing anyway, but your original handler will not be called.");
|
||||||
|
}
|
||||||
|
application = (Application) context.getApplicationContext();
|
||||||
|
//Setup UCE Handler.
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||||
|
@Override
|
||||||
|
public void uncaughtException(Thread thread, final Throwable throwable) {
|
||||||
|
if (isUCEHEnabled) {
|
||||||
|
Log.e(TAG, "App crashed, executing UCEHandler's UncaughtExceptionHandler", throwable);
|
||||||
|
if (hasCrashedInTheLastSeconds(application)) {
|
||||||
|
Log.e(TAG, "App already crashed recently, not starting custom error activity because we could enter a restart loop. Are you sure that your app does not crash directly on init?", throwable);
|
||||||
|
if (oldHandler != null) {
|
||||||
|
oldHandler.uncaughtException(thread, throwable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setLastCrashTimestamp(application, new Date().getTime());
|
||||||
|
if (!isInBackground || isBackgroundMode) {
|
||||||
|
Log.d(TAG,"Preparing Intent");
|
||||||
|
final Intent intent = new Intent(application, UCEDefaultActivity.class);
|
||||||
|
intent.putExtra(EXTRA_EMAIL_ADDRESSES, COMMA_SEPARATED_EMAIL_ADDRESSES);
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
|
throwable.printStackTrace(pw);
|
||||||
|
String stackTraceString = sw.toString();
|
||||||
|
if (stackTraceString.length() > MAX_STACK_TRACE_SIZE) {
|
||||||
|
String disclaimer = " [stack trace too large]";
|
||||||
|
stackTraceString = stackTraceString.substring(0, MAX_STACK_TRACE_SIZE - disclaimer.length()) + disclaimer;
|
||||||
|
}
|
||||||
|
intent.putExtra(EXTRA_STACK_TRACE, stackTraceString);
|
||||||
|
if (isTrackActivitiesEnabled) {
|
||||||
|
StringBuilder activityLogStringBuilder = new StringBuilder();
|
||||||
|
while (!activityLog.isEmpty()) {
|
||||||
|
activityLogStringBuilder.append(activityLog.poll());
|
||||||
|
}
|
||||||
|
intent.putExtra(EXTRA_ACTIVITY_LOG, activityLogStringBuilder.toString());
|
||||||
|
}
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
Log.d(TAG,"calling startActivity()");
|
||||||
|
application.startActivity(intent);
|
||||||
|
} else {
|
||||||
|
Log.d(TAG,"using oldHandler");
|
||||||
|
if (oldHandler != null) {
|
||||||
|
oldHandler.uncaughtException(thread, throwable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//If it is null (should not be), we let it continue and kill the process or it will be stuck
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final Activity lastActivity = lastActivityCreated.get();
|
||||||
|
if (lastActivity != null) {
|
||||||
|
lastActivity.finish();
|
||||||
|
lastActivityCreated.clear();
|
||||||
|
}
|
||||||
|
killCurrentProcess();
|
||||||
|
} else if (oldHandler != null) {
|
||||||
|
//Pass control to old uncaught exception handler
|
||||||
|
oldHandler.uncaughtException(thread, throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
|
||||||
|
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
|
||||||
|
int currentlyStartedActivities = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||||
|
if (activity.getClass() != UCEDefaultActivity.class) {
|
||||||
|
lastActivityCreated = new WeakReference<>(activity);
|
||||||
|
}
|
||||||
|
if (isTrackActivitiesEnabled) {
|
||||||
|
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " created\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityStarted(Activity activity) {
|
||||||
|
currentlyStartedActivities++;
|
||||||
|
isInBackground = (currentlyStartedActivities == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResumed(Activity activity) {
|
||||||
|
if (isTrackActivitiesEnabled) {
|
||||||
|
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " resumed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityPaused(Activity activity) {
|
||||||
|
if (isTrackActivitiesEnabled) {
|
||||||
|
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " paused\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityStopped(Activity activity) {
|
||||||
|
currentlyStartedActivities--;
|
||||||
|
isInBackground = (currentlyStartedActivities == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityDestroyed(Activity activity) {
|
||||||
|
if (isTrackActivitiesEnabled) {
|
||||||
|
activityLog.add(dateFormat.format(new Date()) + ": " + activity.getClass().getSimpleName() + " destroyed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Log.i(TAG, "UCEHandler has been installed.");
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Context can not be null");
|
||||||
|
}
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
Log.e(TAG, "UCEHandler can not be initialized. Help making it better by reporting this as a bug.", throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* INTERNAL method that tells if the app has crashed in the last seconds.
|
||||||
|
* This is used to avoid restart loops.
|
||||||
|
*
|
||||||
|
* @return true if the app has crashed in the last seconds, false otherwise.
|
||||||
|
*/
|
||||||
|
private static boolean hasCrashedInTheLastSeconds(Context context) {
|
||||||
|
long lastTimestamp = getLastCrashTimestamp(context);
|
||||||
|
long currentTimestamp = new Date().getTime();
|
||||||
|
return (lastTimestamp <= currentTimestamp && currentTimestamp - lastTimestamp < 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ApplySharedPref")
|
||||||
|
private static void setLastCrashTimestamp(Context context, long timestamp) {
|
||||||
|
context.getSharedPreferences(SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE).edit().putLong(SHARED_PREFERENCES_FIELD_TIMESTAMP, timestamp).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void killCurrentProcess() {
|
||||||
|
android.os.Process.killProcess(android.os.Process.myPid());
|
||||||
|
System.exit(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long getLastCrashTimestamp(Context context) {
|
||||||
|
return context.getSharedPreferences(SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE).getLong(SHARED_PREFERENCES_FIELD_TIMESTAMP, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void closeApplication(Activity activity) {
|
||||||
|
activity.finish();
|
||||||
|
killCurrentProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private Context context;
|
||||||
|
private boolean isUCEHEnabled = true;
|
||||||
|
private String commaSeparatedEmailAddresses;
|
||||||
|
private boolean isTrackActivitiesEnabled = false;
|
||||||
|
private boolean isBackgroundModeEnabled = true;
|
||||||
|
|
||||||
|
public Builder(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setUCEHEnabled(boolean isUCEHEnabled) {
|
||||||
|
this.isUCEHEnabled = isUCEHEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setTrackActivitiesEnabled(boolean isTrackActivitiesEnabled) {
|
||||||
|
this.isTrackActivitiesEnabled = isTrackActivitiesEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setBackgroundModeEnabled(boolean isBackgroundModeEnabled) {
|
||||||
|
this.isBackgroundModeEnabled = isBackgroundModeEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addCommaSeparatedEmailAddresses(String commaSeparatedEmailAddresses) {
|
||||||
|
this.commaSeparatedEmailAddresses = (commaSeparatedEmailAddresses != null) ? commaSeparatedEmailAddresses : "";
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UCEHandler build() {
|
||||||
|
return new UCEHandler(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,6 +61,7 @@ import com.github.mikephil.charting.data.BarData;
|
|||||||
import com.github.mikephil.charting.data.BarDataSet;
|
import com.github.mikephil.charting.data.BarDataSet;
|
||||||
import com.github.mikephil.charting.data.BarEntry;
|
import com.github.mikephil.charting.data.BarEntry;
|
||||||
import com.github.mikephil.charting.utils.ValueFormatter;
|
import com.github.mikephil.charting.utils.ValueFormatter;
|
||||||
|
import com.rohitss.uceh.UCEHandler;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
static final String TAG = "MainActivity";
|
static final String TAG = "MainActivity";
|
||||||
@@ -89,7 +90,11 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
Log.i(TAG,"onCreate()");
|
Log.i(TAG,"onCreate()");
|
||||||
|
|
||||||
// Set our custom uncaught exception handler to report issues.
|
// Set our custom uncaught exception handler to report issues.
|
||||||
Thread.setDefaultUncaughtExceptionHandler(new OsdUncaughtExceptionHandler(MainActivity.this));
|
//Thread.setDefaultUncaughtExceptionHandler(new OsdUncaughtExceptionHandler(MainActivity.this));
|
||||||
|
new UCEHandler.Builder(this)
|
||||||
|
.addCommaSeparatedEmailAddresses("crashreports@openseizuredetector.org.uk,")
|
||||||
|
.build();
|
||||||
|
|
||||||
//int i = 5/0; // Force exception to test handler.
|
//int i = 5/0; // Force exception to test handler.
|
||||||
mUtil = new OsdUtil(this,serverStatusHandler);
|
mUtil = new OsdUtil(this,serverStatusHandler);
|
||||||
mConnection = new SdServiceConnection(this);
|
mConnection = new SdServiceConnection(this);
|
||||||
|
|||||||
@@ -163,8 +163,8 @@ public class OsdUncaughtExceptionHandler implements Thread.UncaughtExceptionHand
|
|||||||
"You can review the information being sent in the next screen:"+
|
"You can review the information being sent in the next screen:"+
|
||||||
"\n"+errorContent.toString());
|
"\n"+errorContent.toString());
|
||||||
Dialog dialog = builder.create();
|
Dialog dialog = builder.create();
|
||||||
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
//dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
||||||
//dialog.show();
|
dialog.show();
|
||||||
Looper.loop();
|
Looper.loop();
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
|
|||||||
@@ -91,6 +91,9 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
private final String[] REQUIRED_PERMISSIONS = {
|
private final String[] REQUIRED_PERMISSIONS = {
|
||||||
Manifest.permission.SEND_SMS,
|
Manifest.permission.SEND_SMS,
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||||
|
//Manifest.permission.SYSTEM_ALERT_WINDOW,
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
|
Manifest.permission.WAKE_LOCK,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -342,6 +345,11 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
|
|
||||||
fname = fname + "_" + dateStr + ".txt";
|
fname = fname + "_" + dateStr + ".txt";
|
||||||
// Open output directory on SD Card.
|
// Open output directory on SD Card.
|
||||||
|
if (ContextCompat.checkSelfPermission(mContext,
|
||||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Log.e(TAG,"ERROR: We do not have permission to write to external storage");
|
||||||
|
} else {
|
||||||
if (isExternalStorageWritable()) {
|
if (isExternalStorageWritable()) {
|
||||||
try {
|
try {
|
||||||
FileWriter of = new FileWriter(getDataStorageDir().toString()
|
FileWriter of = new FileWriter(getDataStorageDir().toString()
|
||||||
@@ -349,9 +357,9 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
if (msgStr != null) {
|
if (msgStr != null) {
|
||||||
String dateTimeStr = tnow.format("%Y-%m-%d %H:%M:%S");
|
String dateTimeStr = tnow.format("%Y-%m-%d %H:%M:%S");
|
||||||
Log.v(TAG, "writing msgStr");
|
Log.v(TAG, "writing msgStr");
|
||||||
of.append(dateTimeStr+", "
|
of.append(dateTimeStr + ", "
|
||||||
+tnow.toMillis(true)+", "
|
+ tnow.toMillis(true) + ", "
|
||||||
+msgStr+"<br/>\n");
|
+ msgStr + "<br/>\n");
|
||||||
}
|
}
|
||||||
of.close();
|
of.close();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@@ -362,6 +370,7 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
Log.e(TAG, "ERROR - Can not Write to External Folder");
|
Log.e(TAG, "ERROR - Can not Write to External Folder");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Checks if external storage is available for read and write */
|
/* Checks if external storage is available for read and write */
|
||||||
public boolean isExternalStorageWritable() {
|
public boolean isExternalStorageWritable() {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import com.getpebble.android.kit.PebbleKit;
|
|||||||
import com.getpebble.android.kit.util.PebbleDictionary;
|
import com.getpebble.android.kit.util.PebbleDictionary;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.jtransforms.fft.DoubleFFT_1D;
|
import org.jtransforms.fft.DoubleFFT_1D;
|
||||||
|
|
||||||
@@ -373,7 +374,12 @@ public class SdDataSourceGarmin extends SdDataSource {
|
|||||||
Log.v(TAG,"updateFromJSON - dataType="+dataTypeStr);
|
Log.v(TAG,"updateFromJSON - dataType="+dataTypeStr);
|
||||||
if (dataTypeStr.equals("raw")) {
|
if (dataTypeStr.equals("raw")) {
|
||||||
Log.v(TAG,"updateFromJSON - processing raw data");
|
Log.v(TAG,"updateFromJSON - processing raw data");
|
||||||
|
try {
|
||||||
mSdData.mHR = dataObject.getDouble("HR");
|
mSdData.mHR = dataObject.getDouble("HR");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
// if we get 'null' HR (For example if the heart rate is not working)
|
||||||
|
mSdData.mHR = -1;
|
||||||
|
}
|
||||||
JSONArray accelVals = dataObject.getJSONArray("data");
|
JSONArray accelVals = dataObject.getJSONArray("data");
|
||||||
Log.v(TAG, "Received " + accelVals.length() + " acceleration values");
|
Log.v(TAG, "Received " + accelVals.length() + " acceleration values");
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ import java.util.*;
|
|||||||
|
|
||||||
import android.text.format.Time;
|
import android.text.format.Time;
|
||||||
|
|
||||||
|
import com.rohitss.uceh.UCEHandler;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Based on example at:
|
* Based on example at:
|
||||||
@@ -169,15 +171,18 @@ public class SdServer extends Service implements SdDataReceiver, SdLocationRecei
|
|||||||
mUtil.writeToSysLogFile("SdServer.onCreate()");
|
mUtil.writeToSysLogFile("SdServer.onCreate()");
|
||||||
|
|
||||||
// Set our custom uncaught exception handler to report issues.
|
// Set our custom uncaught exception handler to report issues.
|
||||||
Thread.setDefaultUncaughtExceptionHandler(
|
//Thread.setDefaultUncaughtExceptionHandler(
|
||||||
new OsdUncaughtExceptionHandler(SdServer.this));
|
// new OsdUncaughtExceptionHandler(SdServer.this));
|
||||||
|
new UCEHandler.Builder(this)
|
||||||
|
.addCommaSeparatedEmailAddresses("crashreports@openseizuredetector.org.uk,")
|
||||||
|
.build();
|
||||||
//int i = 5/0; // Force exception to test handler.
|
//int i = 5/0; // Force exception to test handler.
|
||||||
|
|
||||||
|
|
||||||
// Create a wake lock, but don't use it until the service is started.
|
// Create a wake lock, but don't use it until the service is started.
|
||||||
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
|
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
|
||||||
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
|
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
|
||||||
"MyWakelockTag");
|
"OSD:WakeLock");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ import android.widget.Button;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.rohitss.uceh.UCEHandler;
|
||||||
|
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
@@ -82,7 +84,11 @@ public class StartupActivity extends Activity {
|
|||||||
Log.i(TAG,"onCreate()");
|
Log.i(TAG,"onCreate()");
|
||||||
|
|
||||||
// Set our custom uncaught exception handler to report issues.
|
// Set our custom uncaught exception handler to report issues.
|
||||||
Thread.setDefaultUncaughtExceptionHandler(new OsdUncaughtExceptionHandler(StartupActivity.this));
|
//Thread.setDefaultUncaughtExceptionHandler(new OsdUncaughtExceptionHandler(StartupActivity.this));
|
||||||
|
new UCEHandler.Builder(this)
|
||||||
|
.addCommaSeparatedEmailAddresses("crashreports@openseizuredetector.org.uk,")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
mHandler = new Handler();
|
mHandler = new Handler();
|
||||||
mUtil = new OsdUtil(this, mHandler);
|
mUtil = new OsdUtil(this, mHandler);
|
||||||
@@ -103,6 +109,10 @@ public class StartupActivity extends Activity {
|
|||||||
PreferenceManager.setDefaultValues(this, R.xml.camera_prefs, true);
|
PreferenceManager.setDefaultValues(this, R.xml.camera_prefs, true);
|
||||||
PreferenceManager.setDefaultValues(this, R.xml.general_prefs, true);
|
PreferenceManager.setDefaultValues(this, R.xml.general_prefs, true);
|
||||||
PreferenceManager.setDefaultValues(this, R.xml.network_datasource_prefs, true);
|
PreferenceManager.setDefaultValues(this, R.xml.network_datasource_prefs, true);
|
||||||
|
PreferenceManager.setDefaultValues(this, R.xml.pebble_datasource_prefs, true);
|
||||||
|
PreferenceManager.setDefaultValues(this, R.xml.garmin_datasource_prefs, true);
|
||||||
|
PreferenceManager.setDefaultValues(this, R.xml.seizure_detector_prefs, true);
|
||||||
|
PreferenceManager.setDefaultValues(this, R.xml.network_passive_datasource_prefs, true);
|
||||||
|
|
||||||
|
|
||||||
Button b;
|
Button b;
|
||||||
@@ -174,6 +184,14 @@ public class StartupActivity extends Activity {
|
|||||||
mUtil.writeToSysLogFile("StartupActivity.onStart()");
|
mUtil.writeToSysLogFile("StartupActivity.onStart()");
|
||||||
TextView tv;
|
TextView tv;
|
||||||
|
|
||||||
|
if (mUtil.arePermissionsOK()) {
|
||||||
|
Log.i(TAG,"onStart() - Permissions OK");
|
||||||
|
} else {
|
||||||
|
Log.i(TAG,"onStart() - Permissions Not OK - requesting them");
|
||||||
|
mUtil.requestPermissions(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
String versionName = mUtil.getAppVersionName();
|
String versionName = mUtil.getAppVersionName();
|
||||||
tv = (TextView) findViewById(R.id.appNameTv);
|
tv = (TextView) findViewById(R.id.appNameTv);
|
||||||
tv.setText("OpenSeizureDetector V" + versionName);
|
tv.setText("OpenSeizureDetector V" + versionName);
|
||||||
@@ -198,6 +216,8 @@ public class StartupActivity extends Activity {
|
|||||||
mUsingPebbleDataSource = true;
|
mUsingPebbleDataSource = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (mUtil.isServerRunning()) {
|
if (mUtil.isServerRunning()) {
|
||||||
Log.i(TAG, "onStart() - server running - stopping it");
|
Log.i(TAG, "onStart() - server running - stopping it");
|
||||||
mUtil.writeToSysLogFile("StartupActivity.onStart() - server already running - stopping it.");
|
mUtil.writeToSysLogFile("StartupActivity.onStart() - server already running - stopping it.");
|
||||||
|
|||||||
89
app/src/main/res/layout/default_error_activity.xml
Normal file
89
app/src/main/res/layout/default_error_activity.xml
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:fadeScrollbars="false"
|
||||||
|
android:scrollbars="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/ask_for_error_log"
|
||||||
|
android:textColor="#212121"
|
||||||
|
android:textSize="18sp"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_view_error_log"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="View Error Log"
|
||||||
|
android:textColor="#212121"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_copy_error_log"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text="Copy Error Log"
|
||||||
|
android:textColor="#212121"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_share_error_log"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text="Share Error Log"
|
||||||
|
android:textColor="#212121"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_email_error_log"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text="Email Error Log"
|
||||||
|
android:textColor="#212121"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_save_error_log"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text="Save Error Log"
|
||||||
|
android:textColor="#212121"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_close_app"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="Close App"
|
||||||
|
android:textColor="#212121"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/copyright_info"
|
||||||
|
android:textColor="#212121"
|
||||||
|
android:textSize="14sp"/>
|
||||||
|
</LinearLayout>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">OpenSeizureDetector</string>
|
<string name="app_name">OpenSeizureDetector</string>
|
||||||
|
<string name="ask_for_error_log">Sorry, OpenSeizureDetector Has Crashed. Please Email this log file to us so we can work out what happened and fix it.\nThanks, Graham.</string>
|
||||||
<!-- TODO: Remove or change this placeholder text -->
|
<string name="email_welcome_note">Dear OpenSeizureDetector,\n\nApplication is just crashed, please check following error log for more details.\n\n\n</string>
|
||||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
<string name="copyright_info">OpenSeizureDetector (Using UCE Handler\nCopyright © 2018 Rohit Sahebrao Surwase.)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ allprojects {
|
|||||||
url 'https://maven.google.com/'
|
url 'https://maven.google.com/'
|
||||||
name 'Google'
|
name 'Google'
|
||||||
}
|
}
|
||||||
|
//maven { url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user