在网上找了一些BaseActivity的实现,现结合Application,方便android应用开发
下面用一个例子说明,程序捕捉到异常后自动重新启动。
package com.brian.example; import android.os.Bundle; public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iniView(); } @Override void iniView() { System.out.println("hello"); int[] ints = new int[1]; System.out.println(ints[1]);//数组溢出,如果不做处理则会显示程序停止运行 } }
Application类的实现,负责应用程序全局异常的捕捉。
package com.brian.example; import java.io.File; import java.io.FileOutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.lang.Thread.UncaughtExceptionHandler; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import android.app.Activity; import android.app.AlarmManager; import android.app.Application; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Environment; /** * 1、收集所有 avtivity 用于彻底退出应用 * 2、捕获崩溃异常,保存错误日志,并重启应用 */ public class MyApplication extends Application { // activity对象列表,用于activity统一管理 private List<Activity> activityList; // 异常捕获 protected boolean isNeedCaughtExeption = true;// 是否捕获未知异常 private PendingIntent restartIntent; private MyUncaughtExceptionHandler uncaughtExceptionHandler; private String packgeName; @Override public void onCreate() { super.onCreate(); activityList = new ArrayList<Activity>(); packgeName = getPackageName(); if (isNeedCaughtExeption) { cauchException(); } } // -------------------异常捕获-----捕获异常后重启应用-----------------// private void cauchException() { Intent intent = new Intent(); // 参数1:包名,参数2:程序入口的activity intent.setClassName(packgeName, packgeName + ".MainActivity");//设置程序入口 restartIntent = PendingIntent.getActivity(getApplicationContext(), -1, intent, Intent.FLAG_ACTIVITY_NEW_TASK); // 程序崩溃时触发线程 uncaughtExceptionHandler = new MyUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler); } // 创建服务用于捕获崩溃异常 private class MyUncaughtExceptionHandler implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread thread, Throwable ex) { // 保存错误日志 saveCatchInfo2File(ex); // 1秒钟后重启应用 AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE); mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); // 关闭当前应用 finishAllActivity(); finishProgram(); } }; /** * 保存错误信息到文件中 * * @return 返回文件名称 */ private String saveCatchInfo2File(Throwable ex) { Writer writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); ex.printStackTrace(printWriter); Throwable cause = ex.getCause(); while (cause != null) { cause.printStackTrace(printWriter); cause = cause.getCause(); } printWriter.close(); String sb = writer.toString(); try { DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.CHINA); String time = formatter.format(new Date()); String fileName = time + ".txt"; System.out.println("fileName:" + fileName); if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { String filePath = Environment.getExternalStorageDirectory() + "/HKDownload/" + packgeName + "/crash/"; File dir = new File(filePath); if (!dir.exists()) { if (!dir.mkdirs()) { // 创建目录失败: 一般是因为SD卡被拔出了 return ""; } } System.out.println("filePath + fileName:" + filePath + fileName); FileOutputStream fos = new FileOutputStream(filePath + fileName); fos.write(sb.getBytes()); fos.close(); //文件保存完了之后,在应用下次启动的时候去检查错误日志,发现新的错误日志,就发送给开发者 } return fileName; } catch (Exception e) { System.out.println("an error occured while writing file..." + e.getMessage()); } return null; } // ------------------------------activity管理-----------------------// // activity管理:从列表中移除activity public void removeActivity(Activity activity) { activityList.remove(activity); } // activity管理:添加activity到列表 public void addActivity(Activity activity) { activityList.add(activity); } // activity管理:结束所有activity public void finishAllActivity() { for (Activity activity : activityList) { if (null != activity) { activity.finish(); } } } // 结束线程,一般与finishAllActivity()一起使用 // 例如: finishAllActivity;finishProgram(); public void finishProgram() { finishAllActivity(); android.os.Process.killProcess(android.os.Process.myPid()); } }
package com.brian.example; import android.app.Application; import android.app.ProgressDialog; import android.content.Context; import android.content.SharedPreferences; /** * Activity的支持类接口,主要定义了Activity中常用的功能 */ public interface IBaseActivity { /** * 获取Application对象 * @return */ public abstract Application getApplication(); /** * 开启服务 */ public abstract void startService(); /** * 停止服务 */ public abstract void stopService(); /** * 判断是否有网络连接,若没有,则弹出网络设置对话框,返回false */ public abstract boolean validateInternet(); /** * 判断是否有网络连接,没有返回false */ public abstract boolean hasInternetConnected(); /** * 退出应用 */ public abstract void isExit(); /** * 判断GPS是否已经开启. */ public abstract boolean hasLocationGPS(); /** * 判断基站是否已经开启. */ public abstract boolean hasLocationNetWork(); /** * 检查内存卡. */ public abstract void checkMemoryCard(); /** * 获取进度条. */ public abstract ProgressDialog getProgressDialog(); /** * 返回当前Activity上下文. */ public abstract Context getContext(); /** * 获取当前登录用户的SharedPreferences配置. */ public SharedPreferences getLoginUserSharedPre(); /** * 用户是否在线(当前网络是否重连成功) */ public boolean getUserOnlineState(); /** * 设置用户在线状态 true 在线 false 不在线 */ public void setUserOnlineState(boolean isOnline); /** * 发出Notification的method. * * @param iconId 图标 * @param contentTitle 标题 * @param contentText 内容 * @param activity */ public void PushNotification(int iconId, String contentTitle, String contentText, Class<?> activity, String from); }
package com.brian.example; import android.app.Activity; import android.app.AlertDialog; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.location.LocationManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; import android.os.Environment; import android.provider.Settings; import android.view.inputmethod.InputMethodManager; /** * Activity的基类,实现了IActivitySupport接口 */ public abstract class BaseActivity extends Activity implements IBaseActivity { protected Context mContext = null; protected SharedPreferences preferences; protected MyApplication myApplication; protected ProgressDialog pg = null; protected NotificationManager notificationManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mContext = this; preferences = getSharedPreferences("TAG", 0); notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); pg = new ProgressDialog(mContext); myApplication = (MyApplication) this.getApplication(); } /** * 初始化页面布局 */ abstract void iniView(); @Override public ProgressDialog getProgressDialog() { return pg; } /** * 在这里开启所有需要开启的服务 */ @Override public void startService() { } /** * 在这里关闭所有需要开启的服务 */ @Override public void stopService() { } /** * 停止服务并结束所有的Activity退出应用 */ @Override public void isExit() { new AlertDialog.Builder(mContext).setTitle("确定退出吗?") .setNeutralButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { stopService(); myApplication.finishProgram(); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }).show(); } /** * 判断是否有网络连接,没有返回false */ @Override public boolean hasInternetConnected() { ConnectivityManager manager = (ConnectivityManager) mContext .getSystemService(Context.CONNECTIVITY_SERVICE); if (manager != null) { NetworkInfo network = manager.getActiveNetworkInfo(); if (network != null && network.isConnectedOrConnecting()) { return true; } } return false; } /** * 判断是否有网络连接,若没有,则弹出网络设置对话框,返回false */ @Override public boolean validateInternet() { ConnectivityManager manager = (ConnectivityManager) mContext .getSystemService(Context.CONNECTIVITY_SERVICE); if (manager == null) { openWirelessSet(); return false; } else { NetworkInfo[] info = manager.getAllNetworkInfo(); if (info != null) { for (int i = 0; i < info.length; i++) { if (info[i].getState() == NetworkInfo.State.CONNECTED) { return true; } } } } openWirelessSet(); return false; } /** * 判断GPS定位服务是否开启 */ @Override public boolean hasLocationGPS() { LocationManager manager = (LocationManager) mContext .getSystemService(Context.LOCATION_SERVICE); if (manager .isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) { return true; } else { return false; } } /** * 判断基站定位是否开启 */ @Override public boolean hasLocationNetWork() { LocationManager manager = (LocationManager) mContext .getSystemService(Context.LOCATION_SERVICE); if (manager .isProviderEnabled(android.location.LocationManager.NETWORK_PROVIDER)) { return true; } else { return false; } } /** * 检查内存卡可读 */ @Override public void checkMemoryCard() { if (!Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState())) { new AlertDialog.Builder(mContext) .setTitle("检测内存卡") .setMessage("请检查内存卡") .setPositiveButton("设置", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); Intent intent = new Intent(Settings.ACTION_SETTINGS); mContext.startActivity(intent); } }) .setNegativeButton("退出", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }).create().show(); } } /** * 打开网络设置对话框 */ public void openWirelessSet() { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext); dialogBuilder .setTitle("网络设置") .setMessage("检查网络") .setPositiveButton("网络设置", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS); mContext.startActivity(intent); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int whichButton) { dialog.cancel(); } }); dialogBuilder.show(); } /** * 关闭键盘 */ public void closeInput() { InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); if (inputMethodManager != null && this.getCurrentFocus() != null) { inputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus() .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } } /** * 发出Notification * @param iconId 图标 * @param contentTitle 标题 * @param contentText 内容 * @param activity */ @SuppressWarnings("deprecation") public void PushNotification(int iconId, String contentTitle, String contentText, Class<?> activity, String to) { // 创建新的Intent,作为点击Notification留言条时, 会运行的Activity Intent notifyIntent = new Intent(this, activity); notifyIntent.putExtra("to", to); // 创建PendingIntent作为设置递延运行的Activity PendingIntent appIntent = PendingIntent.getActivity(mContext, 0, notifyIntent, 0); /* 创建Notication,并设置相关参数 */ Notification myNoti = new Notification(); // 点击自动消失 myNoti.flags = Notification.FLAG_AUTO_CANCEL; /* 设置statusbar显示的icon */ myNoti.icon = iconId; /* 设置statusbar显示的文字信息 */ myNoti.tickerText = contentTitle; /* 设置notification发生时同时发出默认声音 */ myNoti.defaults = Notification.DEFAULT_SOUND; /* 设置Notification留言条的参数 */ myNoti.setLatestEventInfo(mContext, contentTitle, contentText, appIntent); /* 送出Notification */ notificationManager.notify(0, myNoti); } /** * 返回上下文对象 */ @Override public Context getContext() { return mContext; } /** * 返回登录用户的SharedPreferences对象 */ @Override public SharedPreferences getLoginUserSharedPre() { return preferences; } /** * 获取用户在线状态 */ @Override public boolean getUserOnlineState() { return false; } /** * 设置用户在线状态 */ @Override public void setUserOnlineState(boolean isOnline) { } }
使用MyApplication需要在清单文件里面配置:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.brian.example" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <application android:name="com.brian.example.MyApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.brian.example.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>