[2016-06-30]最新的全局异常处理DRCrashHandler已经集成在DR_support_lib库中
具体请看: https://coding.net/u/wrcold520/p/DR_support_lib/git/tree/master
[2016-06-28] 1 增加log4j的支持 [2016-06-28] 2 增加全局异常处理(可自定义程序崩溃提示消息,自定义发送错误报告到服务器) [2016-06-28] 3 增加两种应用退出方法:① appExit,结束掉所有Acitivity的生命周期,正常退出;② appKill,结束掉所有Acitivity的生命周期,杀掉程序进程后退出。 [2016-06-29] 4 增加透明状态栏和导航栏(默认开启,蓝色背景)
在Android程序中,我们通常会在可能发生错误的地方加上try {} catch (Exception e) {}语句来捕获异常,但是,我们无法保证程序就一定不会出错,比如,你玩Android游戏的过程中经常会碰到黑屏或者直接退出的情况,那么这些异常就应该是没有被捕获到(一般获取到都会提示用户错误,并提示用户是否将错误上传至服务器),那么现在我们来看下如何捕获全局异常,然后自己处理。
1、新建DRCrashHandler.java(这是一个抽象类,我放在了DR_supprot_lib库中,以便以后再写应用程序的时候直接使用,里面用到了一些变量是DRConstants类中的,这是一个常量类,用来定义常用的常量的)
默认Toast弹窗提示用户(消息可以自定义)
package cn.dr.lib.app;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.apache.log4j.Logger;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Looper;
import android.widget.Toast;
import cn.dr.lib.common.DRConstants;
import cn.dr.lib.utils.DateUtil;
import cn.dr.lib.utils.FileUtil;
/**
* DarkRanger的全局异常处理类
*
* @author DarkRanger
*
*/
public abstract class DRCrashHandler implements UncaughtExceptionHandler {
/** log4j **/
private static final Logger log = Logger.getLogger(DRCrashHandler.class);
/** 系统默认的UncaughtException处理类 **/
private Thread.UncaughtExceptionHandler mDefaultHandler;
/** 程序context **/
private DRApplication mContext;
/** 存储设备信息和异常信息 **/
private Map<String, String> mInfos = new HashMap<String, String>();
/** 程序出错提示信息 **/
private String mDRTipMsg = "抱歉,程序异常,3s后退出!";
/** 设置crash文件位置 **/
private String mDRCrashFilePath = DRConstants.CRASH_FILE_PATH;
/** 生成的log文件 **/
private File logFile;
/** 生成的crash文件 **/
private File crashFile;
/**
* 初始化
*
* @param context
*/
public void init(DRApplication context) {
log.info("DRCrashHandler is Ready For Application! ");
// 1、上下文
mContext = context;
// 2、获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// 3、初始化参数
initParams();
// 4、设置当前CrashHandler为默认处理异常类
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
* 3.1 初始化参数 <br/>
* <br/>
*
* {@link #setTipMsg(String)} setTipMsg("this is crash tip msg!!!"); <br/>
* {@link #setCrashFilePath(String)}
* setCrashFilePath(Constants.CRASH_FILE_PATH); <br/>
* <br/>
*
* 如果想使用自己的CrashHandler,则复写initParams()方,然后设置参数<br/>
*
* <code>
* public class MyCrashHandler extends DRCrashHandler {<br/>
* private static final Logger log = Logger.getLogger(MyCrashHandler.class);<br/>
*
* @Override<br/>
* public void initParams() {<br/>
* log.trace("MyCrashHandler: initParams()");<br/>
*
* setDRTipMsg("MyCrashHandler tip msg!!!");<br/>
* setDRCrashFilePath(Constants.CRASH_FILE_PATH);<br/>
* }<br/>
* }<br/>
* </code>
*/
public abstract void initParams();
@Override
public void uncaughtException(Thread thread, Throwable ex) {
log.info("DRCrashHandler dispatcher uncaughtException! ");
if (mDefaultHandler != null && !handlerException(ex)) {
mDefaultHandler.uncaughtException(thread, ex);
} else {
// 程序休眠3s后退出
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
((DRApplication) mContext.getApplicationContext()).appExit();
}
}
/**
* 5、处理异常<br>
* <br>
*
* 5.1 收集设备参数信息<br>
* 5.2 弹出窗口提示信息<br>
* 5.3 保存log和crash到文件<br>
* 5.4 发送log和crash到服务器<br>
*
* @param ex
* @return 是否处理了异常
*/
protected boolean handlerException(Throwable ex) {
log.info("DRCrashHandler is handling Exception! ");
if (ex == null) {
return false;
} else {
// 5.1 收集设备参数信息
collectDeviceInfo(mContext);
// 5.2 弹出窗口提示信息
new Thread(new Runnable() {
public void run() {
log.info("DRCrashHandler is ready send crash-info to device!");
Looper.prepare();
Toast.makeText(mContext, getDRTipMsg(), Toast.LENGTH_SHORT).show();
Looper.loop();
}
}).start();
// 5.3 保存log和crash到文件
saveLogAndCrash(ex);
// 5.4 发送log和crash到服务器
sendLogAndCrash();
return true;
}
}
/**
* 5.1 收集设备信息
*
* @param ctx
*/
protected void collectDeviceInfo(Context ctx) {
log.info("DRCrashHandler is collecting DeviceInfo! ");
try {
PackageManager pm = ctx.getPackageManager();
PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
if (pi != null) {
String versionName = pi.versionName == null ? "null" : pi.versionName;
String versionCode = pi.versionCode + "";
mInfos.put("versionName", versionName);
mInfos.put("versionCode", versionCode);
}
} catch (NameNotFoundException e) {
log.error("An error occured when collect package info, Error: " + e);
}
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
mInfos.put(field.getName(), field.get(null).toString());
} catch (Exception e) {
log.error("An error occured when collect crash info, Error: " + e);
}
}
}
/**
* 5.3 保存log和crash到文件
*
* @param ex
*/
protected void saveLogAndCrash(Throwable ex) {
log.info("DRCrashHandler is saving Log! ");
StringBuffer sb = new StringBuffer();
sb.append("[DateTime: " + DateUtil.date2String(new Date()) + "]\n");
sb.append("[DeviceInfo: ]\n");
// 遍历infos
for (Map.Entry<String, String> entry : mInfos.entrySet()) {
String key = entry.getKey().toLowerCase(Locale.getDefault());
String value = entry.getValue();
sb.append(" " + key + ": " + value + "\n");
}
// 将错误手机到writer中
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
ex.printStackTrace(pw);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(pw);
cause = cause.getCause();
}
pw.close();
String result = writer.toString();
sb.append("[Excetpion: ]\n");
sb.append(result);
// 将异常写入日志文件
log.error(result);
// 5.3.1 记录异常到特定文件中
saveToCrashFile(sb.toString());
}
/**
* 5.3.1写入文本
*
* @param crashText
*/
protected void saveToCrashFile(String crashText) {
log.info("DRCrashHandler is writing crash-info to CrashFile(" + this.mDRCrashFilePath + ")! ");
crashFile = new File(mDRCrashFilePath);
// 创建文件(自己写的操作文件相关的工具类)
FileUtil.createFileAndFolder(crashFile);
// 追加文本(自己写的操作文件相关的工具类)
FileUtil.appendToFile(crashFile, crashText);
}
/**
* 5.4 发送log和crash到服务器
*/
protected void sendLogAndCrash() {
logFile = new File(mContext.getDrLogHelper().getLog4jFilePath());
crashFile = new File(getDRCrashFilePath());
// 5.4.1
sendToServer(logFile, crashFile);
}
/**
* 5.4.1 将错误报告发送到服务器
*
* @param crashFile
* @param logFile
*/
protected abstract void sendToServer(File logFile, File crashFile);
public String getDRTipMsg() {
return mDRTipMsg;
}
/**
* 设置程序崩溃提示信息
*
* @param mDRTipMsg
*/
public void setDRTipMsg(String mDRTipMsg) {
this.mDRTipMsg = mDRTipMsg;
}
public String getDRCrashFilePath() {
return mDRCrashFilePath;
}
/**
* 设置记录崩溃信息的文件位置
*
* @param mDRCrashFilePath
*/
public void setDRCrashFilePath(String mDRCrashFilePath) {
this.mDRCrashFilePath = mDRCrashFilePath;
}
}
2、新建DRApplication.java(抽象类,里面用到了Log4j,上一篇有讲到如果在Android中集成Log4j,这里在Application中使用DRLogHelper来初始化log4j)
package cn.dr.lib.app;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import org.apache.log4j.Logger;
import android.app.Activity;
import android.app.Application;
import cn.dr.lib.log.DRLogHelper;
import cn.dr.lib.ui.DRAcitivity;
/**
* DarkRanger的Application
*
* @author DarkRanger
*
*/
public abstract class DRApplication extends Application {
// 当前类的log
private static Logger log;
// Activity列表
private List<DRAcitivity> mActivityList = new LinkedList<DRAcitivity>();
// drLog实例
public DRLogHelper mDRLogHelper = DRLogHelper.getInstance();
// 全局异常处理类的实例
public DRCrashHandler mDRCrashHandler = new DRCrashHandler() {
@Override
public void initParams() {
}
@Override
public void sendToServer(File logFile, File crashFile) {
}
};
@Override
public void onCreate() {
super.onCreate();
// 1、初始化DRLog参数
initDRLogHelperParam();
// 2、初始化DRLog
initDRLogHelper();
// 3、初始化全局异常处理类
initCrashHandler();
}
/**
* 1、初始化DRLog参数,如: <br/>
*
* {@link DRApplication#getDrlog()} DRLog drLog = getDrlog(); <br/>
* {@link DRLogHelper#setLog4jFilePath(String)}
* drLog.setLog4jFilePath(Constants.LOG4J_FILE_PATH); <br/>
* {@link DRLogHelper#setType(cn.dr.lib.log.DRLogHelper.LogType)}
* drLog.setType(LogType.TYPE_LOG4J); <br/>
*
* 只有在子类中完成initDRLogParam参数设置以后才能使用log
*/
protected abstract void initDRLogHelperParam();
/**
* 2、初始化DRLog
*/
private void initDRLogHelper() {
getDrLogHelper().init();
log = Logger.getLogger(DRApplication.class);
}
/**
* 3、初始化CrashHandler
*/
private void initCrashHandler() {
log.trace("DRApplication: initCrashHandler()");
// 3.1
setHandler();
// 3.2
getDRCrashHandler().init(this);
}
/**
*
* 3.1 调用以下方法为mCrashHandler设置实例<br/>
* <br/>
*
* {@link #setCrashHandler(DRCrashHandler)}
*/
public abstract void setHandler();
/**
* 获取DRLog单例
*
* @return
*/
public DRLogHelper getDrLogHelper() {
return mDRLogHelper;
}
public DRCrashHandler getDRCrashHandler() {
return mDRCrashHandler;
}
public void setDRCrashHandler(DRCrashHandler mCrashHandler) {
this.mDRCrashHandler = mCrashHandler;
}
/**
* 添加activity到App的mActivityList
*
* @param activity
*/
public void addActivity(DRAcitivity activity) {
this.mActivityList.add(activity);
}
/**
* 遍历mActivityList,结束每一个activity的声明周期
*/
private void finishActivityList() {
for (Activity activity : mActivityList) {
activity.finish();
}
}
@Override
public void onTerminate() {
log.trace("DRApplication: onTerminate()");
super.onTerminate();
appExit();
}
/**
* 完全退出程序
*/
public void appExit() {
log.trace("DRApplication: appExit()");
finishActivityList();
// 正常退出
System.exit(0);
}
/**
* 出现异常杀掉进程
*/
public void appKill() {
log.trace("DRApplication: appKill()");
finishActivityList();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
3、
首先要说明的是:前面两个类我已经集成在DR_supprot_lib库中,在新的应用程序中只需要继承这两个类,分类初始化一些参数即可。
写个App程序测试:
3.1 新建MyCrashHandler.java继承DRCrashHandler,复写两个抽象方法initParams()和sendToServer()
package cn.darkranger.test;
import java.io.File;
import org.apache.log4j.Logger;
import android.os.Environment;
import cn.dr.lib.app.DRCrashHandler;
public class MyCrashHandler extends DRCrashHandler {
private static final Logger log = Logger.getLogger(MyCrashHandler.class);
String crashFilePath = Environment.getExternalStorageDirectory() + File.separator + "MyApp" + File.separator
+ "Crash.txt";
@Override
public void initParams() {
// 设置程序崩溃提示信息
setDRTipMsg("this is my msg - -");
// 设置程序崩溃的文件位置
setDRCrashFilePath(crashFilePath);
}
@Override
protected void sendToServer(File logFile, File crashFile) {
log.info("logFile: " + logFile + "; crashFile: " + "\naction:sendToServer - -");
// 这里要写上传错误信息到服务器的代码,暂时不写,看需求,自己实现
}
}
3.2 新建MyApplication.java继承DRApplication,复写两个抽象方法initDRLogHelperParam()和setHandler()
package cn.darkranger.test;
import java.io.File;
import org.apache.log4j.Logger;
import android.os.Environment;
import cn.dr.lib.app.DRCrashHandler;
public class MyCrashHandler extends DRCrashHandler {
private static final Logger log = Logger.getLogger(MyCrashHandler.class);
String crashFilePath = Environment.getExternalStorageDirectory() + File.separator + "MyApp" + File.separator
+ "Crash.txt";
@Override
public void initParams() {
// 设置程序崩溃提示信息
setDRTipMsg("this is my msg - -");
// 设置程序崩溃的文件位置
setDRCrashFilePath(crashFilePath);
}
@Override
protected void sendToServer(File logFile, File crashFile) {
log.info("logFile: " + logFile + "; crashFile: " + "\naction:sendToServer - -");
// 这里要写上传错误信息到服务器的代码,暂时不写,看需求,自己实现
}
}
3.3 新建MainActivity,这里暂时不继承DRActivity,继承AppCompatActivity,两个testview,点击第一个,调用DRApplication的退出,点击第二个,抛出异常,我们自己捕获。
package cn.darkranger.test;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView exitTv = (TextView) findViewById(R.id.id_exit);
exitTv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((MyApplication) getApplication()).appExit();
}
});
TextView testCrashTv = (TextView) findViewById(R.id.id_testCrash);
testCrashTv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
throw new IllegalArgumentException("this is an IllegalArgumentException! ");
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
3.4 更改AndroidManifest.xml(添加读写文件的权限,设置application为:cn.darkranger.test.MyApplication)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.darkranger.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name="cn.darkranger.test.MyApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
测试:
运行,点击第一个按钮,退出程序,查看log文件:
[2016-06-30 22:19:09][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)]
[Level: INFO ] - Msg: Log4j is Ready For DRApplication!
[2016-06-30 22:19:09][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)]
[Level: TRACE] - Msg: DRApplication: initCrashHandler()
[2016-06-30 22:19:09][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)]
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application!
[2016-06-30 22:19:12][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)]
[Level: TRACE] - Msg: DRApplication: appExit()
[2016-06-30 22:19:58][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)]
[Level: INFO ] - Msg: Log4j is Ready For DRApplication!
[2016-06-30 22:19:58][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)]
[Level: TRACE] - Msg: DRApplication: initCrashHandler()
[2016-06-30 22:19:58][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)]
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application!
[2016-06-30 22:20:02][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)]
[Level: TRACE] - Msg: DRApplication: appExit()
运行,点击第二个按钮,抛出异常,查看log文件和crash文件:
Log.txt
[2016-06-30 22:19:09][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)]
[Level: INFO ] - Msg: Log4j is Ready For DRApplication!
[2016-06-30 22:19:09][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)]
[Level: TRACE] - Msg: DRApplication: initCrashHandler()
[2016-06-30 22:19:09][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)]
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application!
[2016-06-30 22:19:12][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)]
[Level: TRACE] - Msg: DRApplication: appExit()
[2016-06-30 22:19:58][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)]
[Level: INFO ] - Msg: Log4j is Ready For DRApplication!
[2016-06-30 22:19:58][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)]
[Level: TRACE] - Msg: DRApplication: initCrashHandler()
[2016-06-30 22:19:58][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)]
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application!
[2016-06-30 22:20:02][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)]
[Level: TRACE] - Msg: DRApplication: appExit()
[2016-06-30 22:20:48][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)]
[Level: INFO ] - Msg: Log4j is Ready For DRApplication!
[2016-06-30 22:20:48][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)]
[Level: TRACE] - Msg: DRApplication: initCrashHandler()
[2016-06-30 22:20:48][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)]
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application!
[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.uncaughtException(DRCrashHandler.java:109)]
[Level: INFO ] - Msg: DRCrashHandler dispatcher uncaughtException!
[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.handlerException(DRCrashHandler.java:139)]
[Level: INFO ] - Msg: DRCrashHandler is handling Exception!
[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.collectDeviceInfo(DRCrashHandler.java:175)]
[Level: INFO ] - Msg: DRCrashHandler is collecting DeviceInfo!
[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.saveLogAndCrash(DRCrashHandler.java:206)]
[Level: INFO ] - Msg: DRCrashHandler is saving Log!
[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.run(DRCrashHandler.java:151)]
[Level: INFO ] - Msg: DRCrashHandler is ready send crash-info to device!
[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.saveLogAndCrash(DRCrashHandler.java:233)]
[Level: ERROR] - Msg: java.lang.IllegalArgumentException: this is an IllegalArgumentException!
at cn.darkranger.test.MainActivity$2.onClick(MainActivity.java:33)
at android.view.View.performClick(View.java:4792)
at android.view.View$PerformClick.run(View.java:19936)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5595)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759)
[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.saveToCrashFile(DRCrashHandler.java:246)]
[Level: INFO ] - Msg: DRCrashHandler is writing crash-info to CrashFile(/storage/emulated/0/MyApp/Crash.txt)!
[2016-06-30 22:20:50][Class: cn.dr.lib.utils.FileUtil.createFileAndFolder(FileUtil.java:444)]
[Level: INFO ] - Msg: File[/storage/emulated/0/MyApp/Crash.txt] was created successfully!
[2016-06-30 22:20:50][Class: cn.darkranger.test.MyCrashHandler.sendToServer(MyCrashHandler.java:26)]
[Level: INFO ] - Msg: logFile: /storage/emulated/0/MyApp/Log.txt; crashFile:
action:sendToServer - -
[2016-06-30 22:20:53][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)]
[Level: TRACE] - Msg: DRApplication: appExit()
Crash.txt
[DateTime: 2016-06-30 22:20:50]
[DeviceInfo: ]
supported_64_bit_abis: [Ljava.lang.String;@16d078ef
versioncode: 1
board: mozart
bootloader: unknown
type: user
matchers: [Ljava.lang.String;@3d5b7685
id: HUAWEIM2-801W
time: 1437332391000
brand: HUAWEI
tag: Build
serial: TJF4C15804003585
hardware: hi3635
supported_abis: [Ljava.lang.String;@33767ffc
no_hota: false
cpu_abi: arm64-v8a
radio: unknown
is_debuggable: false
replacements: [Ljava.lang.String;@2dec2cda
manufacturer: HUAWEI
supported_32_bit_abis: [Ljava.lang.String;@3271c1ce
tags: ota-rel-keys,release-keys
cpu_abi2:
unknown: unknown
user: huawei
fingerprint: HUAWEI/M2/HWMozart:5.1.1/HUAWEIM2-801W/C233B009:user/release-keys
host: WUH1000005635
product: M2
versionname: 1.0
display: M2-801WV100R001C233B009
hide_product_info: false
model: HUAWEI M2-801W
device: HWMozart
[Excetpion: ]
java.lang.IllegalArgumentException: this is an IllegalArgumentException!
at cn.darkranger.test.MainActivity$2.onClick(MainActivity.java:33)
at android.view.View.performClick(View.java:4792)
at android.view.View$PerformClick.run(View.java:19936)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5595)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759)
|