android手机开中全局异常处理

 更新时间:2016年9月20日 20:01  点击:1892
本文章介绍一篇关于在手机开发中会出现的一些问题及全局异常处理的处理实现,有需要的朋友可以参考一下本文章。
 代码如下 复制代码

 

package org.wp.activity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
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.Arrays;
import java.util.Properties;
import java.util.TreeSet;

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.util.Log;
import android.widget.Toast;

/**
 *
 *
 * UncaughtExceptionHandler:线程未捕获异常控制器是用来处理未捕获异常的。
 *                           如果程序出现了未捕获异常默认情况下则会出现强行关闭对话框
 *                           实现该接口并注册为程序中的默认未捕获异常处理
 *                           这样当未捕获异常发生时,就可以做些异常处理操作
 *                           例如:收集异常信息,发送错误报告 等。
 *
 * UncaughtException处理类,当程序发生Uncaught异常的时候,由该类来接管程序,并记录发送错误报告.
 */
public class CrashHandler implements UncaughtExceptionHandler {
 /** Debug Log Tag */
 public static final String TAG = "CrashHandler";
 /** 是否开启日志输出, 在Debug状态下开启, 在Release状态下关闭以提升程序性能 */
 public static final boolean DEBUG = true;
 /** CrashHandler实例 */
 private static CrashHandler INSTANCE;
 /** 程序的Context对象 */
 private Context mContext;
 /** 系统默认的UncaughtException处理类 */
 private Thread.UncaughtExceptionHandler mDefaultHandler;
 
 /** 使用Properties来保存设备的信息和错误堆栈信息 */
 private Properties mDeviceCrashInfo = new Properties();
 private static final String VERSION_NAME = "versionName";
 private static final String VERSION_CODE = "versionCode";
 private static final String STACK_TRACE = "STACK_TRACE";
 /** 错误报告文件的扩展名 */
 private static final String CRASH_REPORTER_EXTENSION = ".cr";
 
 /** 保证只有一个CrashHandler实例 */
 private CrashHandler() {
 }

 /** 获取CrashHandler实例 ,单例模式 */
 public static CrashHandler getInstance() {
  if (INSTANCE == null)
   INSTANCE = new CrashHandler();
  return INSTANCE;
 }
 
 /**
  * 初始化,注册Context对象, 获取系统默认的UncaughtException处理器, 设置该CrashHandler为程序的默认处理器
  *
  * @param ctx
  */
 public void init(Context ctx) {
  mContext = ctx;
  mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
  Thread.setDefaultUncaughtExceptionHandler(this);
 }
 
 /**
  * 当UncaughtException发生时会转入该函数来处理
  */
 @Override
 public void uncaughtException(Thread thread, Throwable ex) {
  if (!handleException(ex) && mDefaultHandler != null) {
   // 如果用户没有处理则让系统默认的异常处理器来处理
   mDefaultHandler.uncaughtException(thread, ex);
  } else {
   // Sleep一会后结束程序
   // 来让线程停止一会是为了显示Toast信息给用户,然后Kill程序
   try {
    Thread.sleep(3000);
   } catch (InterruptedException e) {
    Log.e(TAG, "Error : ", e);
   }
   android.os.Process.killProcess(android.os.Process.myPid());
   System.exit(10);
  }
 }

 /**
  * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑
  *
  * @param ex
  * @return true:如果处理了该异常信息;否则返回false
  */
 private boolean handleException(Throwable ex) {
  if (ex == null) {
   return true;
  }
  final String msg = ex.getLocalizedMessage();
  // 使用Toast来显示异常信息
  new Thread() {
   @Override
   public void run() {
    // Toast 显示需要出现在一个线程的消息队列中
    Looper.prepare();
    Toast.makeText(mContext, "程序出错啦:" + msg, Toast.LENGTH_LONG).show();
    Looper.loop();
   }
  }.start();
  // 收集设备信息
  collectCrashDeviceInfo(mContext);
  // 保存错误报告文件
  String crashFileName = saveCrashInfoToFile(ex);
  // 发送错误报告到服务器
  sendCrashReportsToServer(mContext);
  return true;
 }

 /**
  * 收集程序崩溃的设备信息
  *
  * @param ctx
  */
 public void collectCrashDeviceInfo(Context ctx) {
  try {
   // Class for retrieving various kinds of information related to the
   // application packages that are currently installed on the device.
   // You can find this class through getPackageManager().
   PackageManager pm = ctx.getPackageManager();
   // getPackageInfo(String packageName, int flags)
   // Retrieve overall information about an application package that is installed on the system.
   // public static final int GET_ACTIVITIES
   // Since: API Level 1 PackageInfo flag: return information about activities in the package in activities.
   PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
   if (pi != null) {
    // public String versionName The version name of this package,
    // as specified by the <manifest> tag's versionName attribute.
    mDeviceCrashInfo.put(VERSION_NAME, pi.versionName == null ? "not set" : pi.versionName);
    // public int versionCode The version number of this package,
    // as specified by the <manifest> tag's versionCode attribute.
    mDeviceCrashInfo.put(VERSION_CODE, pi.versionCode);
   }
  } catch (NameNotFoundException e) {
   Log.e(TAG, "Error while collect package info", e);
  }
  // 使用反射来收集设备信息.在Build类中包含各种设备信息,
  // 例如: 系统版本号,设备生产商 等帮助调试程序的有用信息
  // 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
  Field[] fields = Build.class.getDeclaredFields();
  for (Field field : fields) {
   try {
    // setAccessible(boolean flag)
    // 将此对象的 accessible 标志设置为指示的布尔值。
    // 通过设置Accessible属性为true,才能对私有变量进行访问,不然会得到一个IllegalAccessException的异常
    field.setAccessible(true);
    mDeviceCrashInfo.put(field.getName(), field.get(null));
    if (DEBUG) {
     Log.d(TAG, field.getName() + " : " + field.get(null));
    }
   } catch (Exception e) {
    Log.e(TAG, "Error while collect crash info", e);
   }
  }
 }
 
 /**
  * 保存错误信息到文件中
  *
  * @param ex
  * @return
  */
 private String saveCrashInfoToFile(Throwable ex) {
  Writer info = new StringWriter();
  PrintWriter printWriter = new PrintWriter(info);
  // printStackTrace(PrintWriter s)
  // 将此 throwable 及其追踪输出到指定的 PrintWriter
  ex.printStackTrace(printWriter);

  // getCause() 返回此 throwable 的 cause;如果 cause 不存在或未知,则返回 null。
  Throwable cause = ex.getCause();
  while (cause != null) {
   cause.printStackTrace(printWriter);
   cause = cause.getCause();
  }

  // toString() 以字符串的形式返回该缓冲区的当前值。
  String result = info.toString();
  printWriter.close();
  mDeviceCrashInfo.put(STACK_TRACE, result);

  try {
   long timestamp = System.currentTimeMillis();
   String fileName = "crash-" + timestamp + CRASH_REPORTER_EXTENSION;
   // 保存文件
   FileOutputStream trace = mContext.openFileOutput(fileName, Context.MODE_PRIVATE);
   mDeviceCrashInfo.store(trace, "");
   trace.flush();
   trace.close();
   return fileName;
  } catch (Exception e) {
   Log.e(TAG, "an error occured while writing report file...", e);
  }
  return null;
 }
 
 /**
  * 把错误报告发送给服务器,包含新产生的和以前没发送的.
  *
  * @param ctx
  */
 private void sendCrashReportsToServer(Context ctx) {
  String[] crFiles = getCrashReportFiles(ctx);
  if (crFiles != null && crFiles.length > 0) {
   TreeSet<String> sortedFiles = new TreeSet<String>();
   sortedFiles.addAll(Arrays.asList(crFiles));

   for (String fileName : sortedFiles) {
    File cr = new File(ctx.getFilesDir(), fileName);
    postReport(cr);
    cr.delete();// 删除已发送的报告
   }
  }
 }

 /**
  * 获取错误报告文件名
  *
  * @param ctx
  * @return
  */
 private String[] getCrashReportFiles(Context ctx) {
  File filesDir = ctx.getFilesDir();
  // 实现FilenameFilter接口的类实例可用于过滤器文件名
  FilenameFilter filter = new FilenameFilter() {
   // accept(File dir, String name)
   // 测试指定文件是否应该包含在某一文件列表中。
   public boolean accept(File dir, String name) {
    return name.endsWith(CRASH_REPORTER_EXTENSION);
   }
  };
  // list(FilenameFilter filter)
  // 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录
  return filesDir.list(filter);
 }

 private void postReport(File file) {
  // TODO 使用HTTP Post 发送错误报告到服务器
  // 这里不再详述,开发者可以根据OPhoneSDN上的其他网络操作
  // 教程来提交错误报告
 }

 /**
  * 在程序启动时候, 可以调用该函数来发送以前没有发送的报告
  */
 public void sendPreviousReportsToServer() {
  sendCrashReportsToServer(mContext);
 }
}

本文章来解决在android2.3.4没有google map的真机上增加google map,有需要的同学可以参考一下。

 

使用Google Map时需依赖以下:
system/app
Location.apk(2.3.4版本不需要这个了)
NetworkLocation.apk
Maps.apk
Street.apk(2.3.4版本不需要这个了)
system/etc/permissions
com.google.android.maps.xml
system/framework
com.google.android.maps.jar

1、通过工具获得root权限;
2、adb shell    su回车 mount -o remount,rw /dev/block/mtdblock3 /system回车
3、adb -d push com.google.android.maps.jar /system/framework/ 或其它手机助手或豌豆夹等工具上传文件
   同时还有文件/system/etc/permissions/com.google.android.maps.xml
  NetworkLocation.apk放到system/app
4、把真机中/etc/permissions/platform.xml文件取出来编辑:<permissions>
<permissions>

本文章今天来帮各位解决在android手机开发中碰到的Activity不能完全退出的问题,现在这个我自己测试可以兼容目前1.6;2.1;2.2;2.3 ; 4.0哦,有需要的同学可以看看。

代码如下:

 代码如下 复制代码

Intent startMain = new Intent(mContext,tabView.class);//这里根据自己需要填写自己的class

                startMain.addCategory(Intent.CATEGORY_HOME);

                startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                mContext.startActivity(startMain);

                try {//原因目前不明,但不加的话就会关闭不了系统 

                    Thread.sleep(1000); 

                } catch (InterruptedException e) { 

                    Log.e(TAG, "Error : ", e); 

                } 

                android.os.Process.killProcess(android.os.Process.myPid());

添加权限

 代码如下 复制代码
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
本文章利用三步就解决了android应用图片缓存这个问题,有需要的同学也可以参考一下。

本文提供三种缓存策略:(1)LRU算法,固定缓存图片数量(max_num),当图片数量超出max_num时,将缓存中最近用的最少的图片删除。(2)FTU算法,固定每张图片的缓存时限,以最后一次使用算起,超过时限后删除。(3)FMU算法,在存储器中固定一定大小的存储空间,超过固定空间后将缓存中占用最大尺寸的图片删除。使用时只需要向方法体中传递图片的URL即可。

使用方法:

1.导入jar;

2. 获取服务;

3.提交url,交给程序去判断是否下载。 

 代码如下 复制代码

public class ImagecachetacticsdemoActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.item);

/*FMU*/
imageCacheManager = ImageCacheManager.getImageCacheService(this,
ImageCacheManager.MODE_FIXED_MEMORY_USED, "memory");
imageCacheManager.setMax_Memory(1024 * 1024);

/*FTU*/
// imageCacheManager = ImageCacheManager.getImageCacheService(this,
// ImageCacheManager.MODE_FIXED_TIMED_USED, "time");
// imageCacheManager.setDelay_millisecond(3 * 60 * 1000);

/*LRU*/
// imageCacheManager = ImageCacheManager.getImageCacheService(this,
// ImageCacheManager.MODE_LEAST_RECENTLY_USED, "num");
// imageCacheManager.setMax_num(5);

// imageCacheManager = ImageCacheManager.getImageCacheService(this,
// ImageCacheManager.MODE_NO_CACHE_USED, "nocache");

mImageView = (ImageView) findViewById(R.id.imageView);
new DownloadTask()
.execute("http://www.touxiang99.com/uploads/allimg/110417/1_110417112640_2.jpg");
}

private class DownloadTask extends AsyncTask<String, Void, Bitmap> {

@Override
protected Bitmap doInBackground(String... params) {
try {
return imageCacheManager.downlaodImage(new URL(params[0]));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

@Override
protected void onPostExecute(Bitmap result) {

mImageView.setImageBitmap(result);
super.onPostExecute(result);
}

@Override
protected void onPreExecute() {
mImageView.setImageResource(R.drawable.ic_launcher);
super.onPreExecute();
}

}

private ImageView mImageView;
private ImageCacheManager imageCacheManager;

json数据格式解析我自己分为两种,一种是普通的,一种是带有数组形式的,下面积们分别举说明一下关于android手机开发中处理方法。

普通形式的:
服务器端返回的json数据格式如下:

 代码如下 复制代码

{"userbean":{"Uid":"100196","Showname":"u75afu72c2u7684u7334u5b50","Avtar":null,"State":1}}

分析代码如下:

 代码如下 复制代码

// TODO 状态处理 500 200
                int res = 0;
                res = httpClient.execute(httpPost).getStatusLine().getStatusCode();
                if (res == 200) {
                    /*
                     * 当返回码为200时,做处理
                     * 得到服务器端返回json数据,并做处理
                     * */
                    HttpResponse httpResponse = httpClient.execute(httpPost);
                    StringBuilder builder = new StringBuilder();
                    BufferedReader bufferedReader2 = new BufferedReader(
                            new InputStreamReader(httpResponse.getEntity().getContent()));
                    String str2 = "";
                    for (String s = bufferedReader2.readLine(); s != null; s = bufferedReader2
                            .readLine()) {
                        builder.append(s);
                    }
                    Log.i("cat", ">>>>>>" + builder.toString());

JSONObject jsonObject = new JSONObject(builder.toString())
                        .getJSONObject("userbean");

                String Uid;
                String Showname;
                String Avtar;
                String State;

                Uid = jsonObject.getString("Uid");
                Showname = jsonObject.getString("Showname");
                Avtar = jsonObject.getString("Avtar");
                State = jsonObject.getString("State");

带数组形式的:
服务器端返回的数据格式为:

 代码如下 复制代码
{"calendar":
    {"calendarlist":
            [
            {"calendar_id":"1705","title":"(u4eb2u5b50)ddssd","category_name":"u9ed8u8ba4u5206u7c7b","showtime":"1288927800","endshowtime":"1288931400","allDay":false},
            {"calendar_id":"1706","title":"(u65c5u884c)","category_name":"u9ed8u8ba4u5206u7c7b","showtime":"1288933200","endshowtime":"1288936800","allDay":false}
            ]
    }
}

分析代码如下:

 代码如下 复制代码
// TODO 状态处理 500 200
                int res = 0;
                res = httpClient.execute(httpPost).getStatusLine().getStatusCode();
                if (res == 200) {
                    /*
                     * 当返回码为200时,做处理
                     * 得到服务器端返回json数据,并做处理
                     * */
                    HttpResponse httpResponse = httpClient.execute(httpPost);
                    StringBuilder builder = new StringBuilder();
                    BufferedReader bufferedReader2 = new BufferedReader(
                            new InputStreamReader(httpResponse.getEntity().getContent()));
                    String str2 = "";
                    for (String s = bufferedReader2.readLine(); s != null; s = bufferedReader2
                            .readLine()) {
                        builder.append(s);
                    }
                    Log.i("cat", ">>>>>>" + builder.toString());
                    /**
                     * 这里需要分析服务器回传的json格式数据,
                     */
                    JSONObject jsonObject = new JSONObject(builder.toString())
                            .getJSONObject("calendar");
                    JSONArray jsonArray = jsonObject.getJSONArray("calendarlist");
                    for(int i=0;i<jsonArray.length();i++){
                        JSONObject jsonObject2 = (JSONObject)jsonArray.opt(i);
                        CalendarInfo calendarInfo = new CalendarInfo();
                        calendarInfo.setCalendar_id(jsonObject2.getString("calendar_id"));
                        calendarInfo.setTitle(jsonObject2.getString("title"));
                        calendarInfo.setCategory_name(jsonObject2.getString("category_name"));
                        calendarInfo.setShowtime(jsonObject2.getString("showtime"));
                        calendarInfo.setEndtime(jsonObject2.getString("endshowtime"));
                        calendarInfo.setAllDay(jsonObject2.getBoolean("allDay"));
                        calendarInfos.add(calendarInfo);
                    }

总结,普通形式的只需用JSONObject ,带数组形式的需要使用JSONArray 将其变成一个list。

[!--infotagslink--]

相关文章

  • Android子控件超出父控件的范围显示出来方法

    下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • Android模拟器上模拟来电和短信配置

    如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
  • 夜神android模拟器设置代理的方法

    夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
  • android自定义动态设置Button样式【很常用】

    为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
  • Android WebView加载html5页面实例教程

    如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
  • 深入理解Android中View和ViewGroup

    深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
  • Android自定义WebView网络视频播放控件例子

    下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
  • Android用MemoryFile文件类读写进行性能优化

    java开发的Android应用,性能一直是一个大问题,,或许是Java语言本身比较消耗内存。本文我们来谈谈Android 性能优化之MemoryFile文件读写。 Android匿名共享内存对外A...2016-09-20
  • Android设置TextView竖着显示实例

    TextView默认是横着显示了,今天我们一起来看看Android设置TextView竖着显示如何来实现吧,今天我们就一起来看看操作细节,具体的如下所示。 在开发Android程序的时候,...2016-10-02
  • C#多线程中的异常处理操作示例

    这篇文章主要介绍了C#多线程中的异常处理操作,涉及C#多线程及异常的捕获、处理等相关操作技巧,需要的朋友可以参考下...2020-06-25
  • android.os.BinderProxy cannot be cast to com解决办法

    本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20
  • Android 实现钉钉自动打卡功能

    这篇文章主要介绍了Android 实现钉钉自动打卡功能的步骤,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下...2021-03-15
  • Android 开发之布局细节对比:RTL模式

    下面我们来看一篇关于Android 开发之布局细节对比:RTL模式 ,希望这篇文章对各位同学会带来帮助,具体的细节如下介绍。 前言 讲真,好久没写博客了,2016都过了一半了,赶紧...2016-10-02
  • C#异常处理中try和catch语句及finally语句的用法示例

    这篇文章主要介绍了C#异常处理中try和catch语句及finally语句的用法示例,finally语句的使用涉及到了C#的垃圾回收特性,需要的朋友可以参考下...2020-06-25
  • Android中使用SDcard进行文件的读取方法

    首先如果要在程序中使用sdcard进行存储,我们必须要在AndroidManifset.xml文件进行下面的权限设置: 在AndroidManifest.xml中加入访问SDCard的权限如下: <!--...2016-09-20
  • Android开发之PhoneGap打包及错误解决办法

    下面来给各位简单的介绍一下关于Android开发之PhoneGap打包及错误解决办法,希望碰到此类问题的同学可进入参考一下哦。 在我安装、配置好PhoneGap项目的所有依赖...2016-09-20
  • 用Intel HAXM给Android模拟器Emulator加速

    Android 模拟器 Emulator 速度真心不给力,, 现在我们来介绍使用 Intel HAXM 技术为 Android 模拟器加速,使模拟器运行度与真机比肩。 周末试玩了一下在Eclipse中使...2016-09-20
  • Android判断当前屏幕是全屏还是非全屏

    在安卓开发时我碰到一个问题就是需要实现全屏,但又需要我们来判断出用户是使用了全屏或非全屏了,下面我分别找了两段代码,大家可参考。 先来看一个android屏幕全屏实...2016-09-20
  • Android开发中布局中的onClick简单完成多控件时的监听的利与弊

    本文章来为各位介绍一篇关于Android开发中布局中的onClick简单完成多控件时的监听的利与弊的例子,希望这个例子能够帮助到各位朋友. 首先在一个控件加上这么一句:and...2016-09-20