Use Firebase Crashlytics

This commit is contained in:
seven332 committed 2018-12-18 14:43:38 +08:00
1 parent f8676b71dc
commit 561e396c97
19 files changed
+8 -509

No files matched your search

@@ -37,7 +37,6 @@ public class AppConfig {
private static final String DOWNLOAD = "download";
private static final String TEMP = "temp";
private static final String IMAGE = "image";
private static final String CRASH = "crash";
private static final String PARSE_ERROR = "parse_error";
private static final String LOGCAT = "logcat";
private static final String DATA = "data";
@@ -95,11 +94,6 @@ public class AppConfig {
return getDirInExternalAppDir(IMAGE);
}
@Nullable
public static File getExternalCrashDir() {
return getDirInExternalAppDir(CRASH);
}
@Nullable
public static File getExternalParseErrorDir() {
return getDirInExternalAppDir(PARSE_ERROR);
@@ -1,205 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* 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.hippo.ehviewer;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Debug;
import android.support.annotation.NonNull;
import com.hippo.scene.StageActivity;
import com.hippo.util.PackageUtils;
import com.hippo.util.ReadableTime;
import com.hippo.yorozuya.FileUtils;
import com.hippo.yorozuya.IOUtils;
import com.hippo.yorozuya.OSUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
public final class Crash {
private Crash() {}
@NonNull
private static String avoidNull(String str) {
return null != str ? str : "null";
}
@SuppressWarnings("deprecation")
private static void collectInfo(Context context, FileWriter fw) throws IOException {
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
if (pi != null) {
String versionName = pi.versionName == null ? "null" : pi.versionName;
String versionCode = String.valueOf(pi.versionCode);
fw.write("======== PackageInfo ========\r\n");
fw.write("PackageName=");fw.write(pi.packageName);fw.write("\r\n");
fw.write("VersionName=");fw.write(versionName);fw.write("\r\n");
fw.write("VersionCode=");fw.write(versionCode);fw.write("\r\n");
String signature = PackageUtils.getSignature(context, pi.packageName);
fw.write("Signature=");fw.write(null != signature ? signature : "null");fw.write("\r\n");
fw.write("\r\n");
}
} catch (PackageManager.NameNotFoundException e) {
fw.write("======== PackageInfo ========\r\n");
fw.write("Can't get package information\r\n");
fw.write("\r\n");
}
// Runtime
String topActivityClazzName = "null";
String topSceneClazzName = "null";
try {
Activity topActivity = ((EhApplication) context.getApplicationContext()).getTopActivity();
if (null != topActivity) {
topActivityClazzName = topActivity.getClass().getName();
if (topActivity instanceof StageActivity) {
Class<?> clazz = ((StageActivity) topActivity).getTopSceneClass();
if (clazz != null) {
topSceneClazzName = clazz.getName();
}
}
}
} catch (Throwable e) {
// Ignore
}
fw.write("======== Runtime ========\r\n");
fw.write("TopActivity=");fw.write(avoidNull(topActivityClazzName));fw.write("\r\n");
fw.write("TopScene=");fw.write(avoidNull(topSceneClazzName));fw.write("\r\n");
fw.write("\r\n");
// Device info
fw.write("======== DeviceInfo ========\r\n");
fw.write("BOARD=");fw.write(Build.BOARD);fw.write("\r\n");
fw.write("BOOTLOADER=");fw.write(Build.BOOTLOADER);fw.write("\r\n");
fw.write("CPU_ABI=");fw.write(Build.CPU_ABI);fw.write("\r\n");
fw.write("CPU_ABI2=");fw.write(Build.CPU_ABI2);fw.write("\r\n");
fw.write("DEVICE=");fw.write(Build.DEVICE);fw.write("\r\n");
fw.write("DISPLAY=");fw.write(Build.DISPLAY);fw.write("\r\n");
fw.write("FINGERPRINT=");fw.write(Build.FINGERPRINT);fw.write("\r\n");
fw.write("HARDWARE=");fw.write(Build.HARDWARE);fw.write("\r\n");
fw.write("HOST=");fw.write(Build.HOST);fw.write("\r\n");
fw.write("ID=");fw.write(Build.ID);fw.write("\r\n");
fw.write("MANUFACTURER=");fw.write(Build.MANUFACTURER);fw.write("\r\n");
fw.write("MODEL=");fw.write(Build.MODEL);fw.write("\r\n");
fw.write("PRODUCT=");fw.write(Build.PRODUCT);fw.write("\r\n");
fw.write("RADIO=");fw.write(Build.getRadioVersion());fw.write("\r\n");
fw.write("SERIAL=");fw.write(Build.SERIAL);fw.write("\r\n");
fw.write("TAGS=");fw.write(Build.TAGS);fw.write("\r\n");
fw.write("TYPE=");fw.write(Build.TYPE);fw.write("\r\n");
fw.write("USER=");fw.write(Build.USER);fw.write("\r\n");
fw.write("CODENAME=");fw.write(Build.VERSION.CODENAME);fw.write("\r\n");
fw.write("INCREMENTAL=");fw.write(Build.VERSION.INCREMENTAL);fw.write("\r\n");
fw.write("RELEASE=");fw.write(Build.VERSION.RELEASE);fw.write("\r\n");
fw.write("SDK=");fw.write(Integer.toString(Build.VERSION.SDK_INT));fw.write("\r\n");
fw.write("MEMORY=");fw.write(FileUtils.humanReadableByteCount(OSUtils.getAppAllocatedMemory(), false));fw.write("\r\n");
fw.write("MEMORY_NATIVE=");fw.write(FileUtils.humanReadableByteCount(Debug.getNativeHeapAllocatedSize(), false));fw.write("\r\n");
fw.write("MEMORY_MAX=");fw.write(FileUtils.humanReadableByteCount(OSUtils.getAppMaxMemory(), false));fw.write("\r\n");
fw.write("MEMORY_TOTAL=");fw.write(FileUtils.humanReadableByteCount(OSUtils.getTotalMemory(), false));fw.write("\r\n");
fw.write("\r\n");
}
public static void getThrowableInfo(Throwable t, FileWriter fw) {
PrintWriter printWriter = new PrintWriter(fw);
t.printStackTrace(printWriter);
Throwable cause = t.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
}
public static void saveCrashInfo2File(Context context, Throwable ex) {
File dir = AppConfig.getExternalCrashDir();
if (dir == null) {
return;
}
String nowString = ReadableTime.getFilenamableTime(System.currentTimeMillis());
String fileName = "crash-" + nowString + ".log";
File file = new File(dir, fileName);
FileWriter fw = null;
try {
fw = new FileWriter(file);
fw.write("TIME=");fw.write(nowString);fw.write("\r\n");
fw.write("\r\n");
collectInfo(context, fw);
fw.write("======== CrashInfo ========\r\n");
getThrowableInfo(ex, fw);
fw.write("\r\n");
fw.flush();
Settings.putCrashFilename(fileName);
} catch (Exception e) {
file.delete();
} finally {
IOUtils.closeQuietly(fw);
}
}
public static boolean hasCrashFile() {
String filename = Settings.getCrashFilename();
if (filename == null) {
return false;
}
File dir = AppConfig.getExternalCrashDir();
if (dir == null) {
return false;
}
return new File(dir, filename).isFile();
}
public static String getCrashContent() {
String filename = Settings.getCrashFilename();
if (filename == null) {
return null;
}
File dir = AppConfig.getExternalCrashDir();
if (dir == null) {
return null;
}
File file = new File(dir, filename);
InputStream is = null;
try {
is = new FileInputStream(file);
return IOUtils.readString(is, "UTF-8");
} catch (IOException e) {
return null;
} finally {
IOUtils.closeQuietly(is);
}
}
public static void resetCrashFile() {
Settings.putCrashFilename(null);
}
}
@@ -56,7 +56,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
public class EhApplication extends RecordingApplication implements Thread.UncaughtExceptionHandler {
public class EhApplication extends RecordingApplication {
private static final String TAG = EhApplication.class.getSimpleName();
@@ -68,8 +68,6 @@ public class EhApplication extends RecordingApplication implements Thread.Uncaug
private static final boolean DEBUG_PRINT_IMAGE_COUNT = false;
private static final long DEBUG_PRINT_INTERVAL = 3000L;
private Thread.UncaughtExceptionHandler mDefaultHandler;
private final IntIdGenerator mIdGenerator = new IntIdGenerator();
private final HashMap<Integer, Object> mGlobalStuffMap = new HashMap<>();
private EhCookieStore mEhCookieStore;
@@ -86,10 +84,6 @@ public class EhApplication extends RecordingApplication implements Thread.Uncaug
@Override
public void onCreate() {
// Prepare to catch crash
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
super.onCreate();
GetText.initialize(this);
@@ -317,34 +311,6 @@ public class EhApplication extends RecordingApplication implements Thread.Uncaug
return application.mHosts;
}
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
try {
ex.printStackTrace();
Crash.saveCrashInfo2File(this, ex);
return true;
} catch (Throwable tr) {
return false;
}
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
mDefaultHandler.uncaughtException(thread, ex);
}
Activity activity = getTopActivity();
if (activity != null) {
activity.finish();
}
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
@NonNull
public static String getDeveloperEmail() {
return "ehviewersu$gmail.com".replace('$', '@');
@@ -16,7 +16,6 @@
package com.hippo.ehviewer;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
@@ -25,7 +24,6 @@ import android.support.annotation.DimenRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.hippo.ehviewer.client.EhConfig;
import com.hippo.ehviewer.client.EhUtils;
import com.hippo.ehviewer.client.data.FavListUrlBuilder;
@@ -35,10 +33,8 @@ import com.hippo.unifile.UniFile;
import com.hippo.yorozuya.FileUtils;
import com.hippo.yorozuya.MathUtils;
import com.hippo.yorozuya.NumberUtils;
import junit.framework.Assert;
import java.io.File;
import junit.framework.Assert;
public class Settings {
@@ -993,21 +989,6 @@ public class Settings {
return getBoolean(KEY_AUTO_CHECK_FOR_UPDATES, DEFAULT_AUTO_CHECK_FOR_UPDATES);
}
/********************
****** Crash
********************/
private static final String KEY_CRASH_FILENAME = "crash_filename";
private static final String DEFAULT_CRASH_FILENAME = null;
public static String getCrashFilename() {
return getString(KEY_CRASH_FILENAME, DEFAULT_CRASH_FILENAME);
}
@SuppressLint("CommitPrefEdits")
public static void putCrashFilename(String value) {
sSettingsPre.edit().putString(KEY_CRASH_FILENAME, value).commit();
}
/********************
****** Advanced
********************/
@@ -45,7 +45,6 @@ import android.widget.TextView;
import android.widget.Toast;
import com.hippo.drawerlayout.DrawerLayout;
import com.hippo.ehviewer.AppConfig;
import com.hippo.ehviewer.Crash;
import com.hippo.ehviewer.EhApplication;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.Settings;
@@ -57,7 +56,6 @@ import com.hippo.ehviewer.client.parser.GalleryPageUrlParser;
import com.hippo.ehviewer.ui.scene.AnalyticsScene;
import com.hippo.ehviewer.ui.scene.BaseScene;
import com.hippo.ehviewer.ui.scene.CookieSignInScene;
import com.hippo.ehviewer.ui.scene.CrashScene;
import com.hippo.ehviewer.ui.scene.DownloadLabelsScene;
import com.hippo.ehviewer.ui.scene.DownloadsScene;
import com.hippo.ehviewer.ui.scene.FavoritesScene;
@@ -126,7 +124,6 @@ public final class MainActivity extends StageActivity
registerLaunchMode(SecurityScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
registerLaunchMode(WarningScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
registerLaunchMode(AnalyticsScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
registerLaunchMode(CrashScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
registerLaunchMode(SignInScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
registerLaunchMode(WebViewSignInScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
registerLaunchMode(CookieSignInScene.class, SceneFragment.LAUNCH_MODE_SINGLE_TASK);
@@ -171,8 +168,6 @@ public final class MainActivity extends StageActivity
return new Announcer(WarningScene.class);
} else if (Settings.getAskAnalytics()) {
return new Announcer(AnalyticsScene.class);
} else if (Crash.hasCrashFile()) {
return new Announcer(CrashScene.class);
} else if (EhUtils.needSignedIn(this)) {
return new Announcer(SignInScene.class);
} else if (Settings.getSelectSite()) {
@@ -202,11 +197,6 @@ public final class MainActivity extends StageActivity
newArgs.putString(AnalyticsScene.KEY_TARGET_SCENE, announcer.getClazz().getName());
newArgs.putBundle(AnalyticsScene.KEY_TARGET_ARGS, announcer.getArgs());
return new Announcer(AnalyticsScene.class).setArgs(newArgs);
} else if (Crash.hasCrashFile()) {
Bundle newArgs = new Bundle();
newArgs.putString(CrashScene.KEY_TARGET_SCENE, announcer.getClazz().getName());
newArgs.putBundle(CrashScene.KEY_TARGET_ARGS, announcer.getArgs());
return new Announcer(CrashScene.class).setArgs(newArgs);
} else if (EhUtils.needSignedIn(this)) {
Bundle newArgs = new Bundle();
newArgs.putString(SignInScene.KEY_TARGET_SCENE, announcer.getClazz().getName());
@@ -1,96 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* 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.hippo.ehviewer.ui.scene;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.hippo.android.resource.AttrResources;
import com.hippo.ehviewer.Crash;
import com.hippo.ehviewer.EhApplication;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.ripple.Ripple;
import com.hippo.util.AppHelper;
import com.hippo.yorozuya.ViewUtils;
public class CrashScene extends SolidScene implements View.OnClickListener {
/*---------------
Whole life cycle
---------------*/
@Nullable
private String mCrash;
/*---------------
View life cycle
---------------*/
@Nullable
private View mCancel;
@Nullable
private View mSend;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCrash = Crash.getCrashContent();
}
@Override
public void onDestroyView() {
super.onDestroyView();
mCrash = null;
}
@Nullable
@Override
public View onCreateView2(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.scene_crash, container, false);
mCancel = ViewUtils.$$(view, R.id.cancel);
mSend = ViewUtils.$$(view, R.id.send);
mCancel.setOnClickListener(this);
mSend.setOnClickListener(this);
boolean isDarkTheme = !AttrResources.getAttrBoolean(getContext2(), R.attr.isLightTheme);
Ripple.addRipple(mCancel, isDarkTheme);
Ripple.addRipple(mSend, isDarkTheme);
return view;
}
@Override
public void onClick(View v) {
MainActivity activity = getActivity2();
if (mSend == v && null != mCrash && null != activity) {
AppHelper.sendEmail(activity, EhApplication.getDeveloperEmail(),
"I found a bug in EhViewer !", mCrash);
}
Crash.resetCrashFile();
// Start new scene and finish it self
if (null != activity) {
startSceneForCheckStep(CHECK_STEP_CRASH, getArguments());
}
finish();
}
}
@@ -18,8 +18,6 @@ package com.hippo.ehviewer.ui.scene;
import android.os.Bundle;
import android.util.Log;
import com.hippo.ehviewer.Crash;
import com.hippo.ehviewer.Settings;
import com.hippo.ehviewer.client.EhUtils;
import com.hippo.scene.Announcer;
@@ -34,9 +32,8 @@ public class SolidScene extends BaseScene {
public static final int CHECK_STEP_SECURITY = 0;
public static final int CHECK_STEP_WARNING = 1;
public static final int CHECK_STEP_ANALYTICS = 2;
public static final int CHECK_STEP_CRASH = 3;
public static final int CHECK_STEP_SIGN_IN = 4;
public static final int CHECK_STEP_SELECT_SITE = 5;
public static final int CHECK_STEP_SIGN_IN = 3;
public static final int CHECK_STEP_SELECT_SITE = 4;
public static final String KEY_TARGET_SCENE = "target_scene";
public static final String KEY_TARGET_ARGS = "target_args";
@@ -54,11 +51,6 @@ public class SolidScene extends BaseScene {
break;
}
case CHECK_STEP_ANALYTICS:
if (Crash.hasCrashFile()) {
startScene(new Announcer(CrashScene.class).setArgs(args));
break;
}
case CHECK_STEP_CRASH:
if (EhUtils.needSignedIn(getContext2())) {
startScene(new Announcer(SignInScene.class).setArgs(args));
break;