您的位置:首页 > 其它

13_综合技术

2016-03-18 09:24 357 查看
综合技术
1、使用CrashHandler来获取应用的crash信息

不管程序怎么写都很难避免不crash,当程序crash后虽然无法让其继续运行,但是如果能够知道程序crash的原因,那么就可以修复错误。但是很多时候产品发布后,如果用户在使用时发生了crash,这个crash信息是很难获取到的,不利于产品的持续发展。

其实可以通过CrashHandler来监视应用的crash信息,给程序设置一个CrashHandler,这样当程序crash时就会调用CrashHandler的uncaughtException方法。在这个方法中我们可以获取crash信息并上传服务器,通过这种方式服务器就能监控程序的运行状况。

在Application的onCreate方法中:

// 设置系统异常处理
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(this));
代码示例:
/**
* 捕獲全局異常
*/
public class CrashHandler implements UncaughtExceptionHandler {
private static final String TAG = "DefaultExceptionHandler";

private Context context;

public CrashHandler(Context context) {
this.context = context;
}

/**
* 当发生异常情况时,系统会回调该接口
*
* @param thread
* @param ex
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// 收集异常信息,写入到sd卡
restoreCrash(thread, ex);
// 发送Crash信息到服务器
sendCrashReport(thread, ex);
// 处理异常
handleException(thread, ex);
// 退出
killProcess(thread);
}

protected void restoreCrash(Thread thread, Throwable ex) {
// 收集异常信息,写入到sd卡
File dir = new File(SystemUtility.getAppCachePath() + "crash");
if (!dir.exists()) {
dir.mkdirs();
}
try {
java.text.DateFormat format1 = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String name = format1.format(new Date(System.currentTimeMillis()))
+ ".log";
PrintStream err = new PrintStream(new File(dir, name));
ex.printStackTrace(err);
} catch (Exception e) {
Log.e(TAG, "sendCrashReport Exception=", e);
}
}

protected void sendCrashReport(Thread thread, Throwable ex) {
// TODO 发送Crash信息到服务器
}

protected void handleException(Thread thread, Throwable ex) {
Log.e(TAG, "handleException#threadId=" + thread.getId()
+ ", threadName=" + thread.getName() + ", exception=", ex);
if (false)
return;
// 提示用户程序崩溃了
new Thread() {
@Override
public void run() {
// 必须这样实现才能显示提示
Looper.prepare();
ToastUtil.showCustomToast(context, "程序崩溃了!-_-,");
Looper.loop();
if (Looper.myLooper() != null) {
Looper.myLooper().quit();
}
}
}.start();
// 间隔3秒,让用户看到提示
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Log.d(TAG, "handleException# Thread.sleep exception=", e);
}
}

protected void killProcess(Thread thread) {
Intent intent = new Intent(BaseApplication.getInstance(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent restartIntent = PendingIntent.getActivity(
BaseApplication.getInstance(), 0, intent,
0);
//退出程序
AlarmManager mgr = (AlarmManager) BaseApplication.getInstance().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100,
restartIntent); // 300后重启应用
AppManager.getAppManager().AppExit(context);
}
}

2、使用multidex来解决方法数越界

在Android中,有一个限制,那就是整个应用的方法数不能超过65536,否则就会出现编译错误,并且程序也无法成功安装到手机上。当项目日益庞大后这个问题就比较容易遇到,Google提供了multidex方案专门用于解决这个问题,通过将一个dex文件拆分为多个dex文件来避免单个dex文件方法数越界的问题。

首先想到的肯定是删除无用的代码和第三方库;之前很多应用都会考虑采用插件化的机制来动态加载部分dex,通过将一个dex拆分成两个或者多个dex,这就在一定程度上解决了方法数越界的问题,但是插件化是一套重量级的技术方案。在gradle中引入multidex

3、Android的动态加载技术

方法越界的另一种解决方案是动态加载,动态加载可以直接加载一个dex形式的文件,将部分代码打包到一个单独的dex文件中,并在程序运行时根据需要去动态加载dex中的类,这种方式既可以解决缓解方法数越界的问题,也可以为程序提供按需加载的特性,同时这还未应用按模块更新提供了可能性。

动态加载技术(也叫插件化技术)在技术驱动型的公司中扮演着相当重要的角色,当项目越来越庞大时,需要通过插件化来减轻应用的内存和CPU占用,还可以实现热插拔,即在不发布新版本的情况下更新某些模块。

在不同的插件化方案各有各的特色,但是它们都必须要解决三个基础性问题:资源访问、Activity生命周期的管理和ClassLoader的管理。

宿主和插件的概念:宿主是指普通的apk,而插件一般是指经过处理的dex或者apk
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息