安卓常用1

1捕获android程序崩溃日志
package xiangde.activity;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

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.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
    
/**  
 * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告. 
 * 
 *  需要在Application中注册,为了要在程序启动器就监控整个程序。
 */    
public class CrashHandler implements UncaughtExceptionHandler {    
        
    public static final String TAG = "CrashHandler";    
        
    //系统默认的UncaughtException处理类     
    private Thread.UncaughtExceptionHandler mDefaultHandler;    
    //CrashHandler实例    
    private static CrashHandler instance;
   //程序的Context对象    
    private Context mContext;    
    //用来存储设备信息和异常信息    
    private Map<String, String> infos = new HashMap<String, String>();    
    
    //用于格式化日期,作为日志文件名的一部分    
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");    
    
    /** 保证只有一个CrashHandler实例 */    
    private CrashHandler() {}    
    
    /** 获取CrashHandler实例 ,单例模式 */    
    public static CrashHandler getInstance() {    
        if(instance == null)
            instance = new CrashHandler();   
        return instance;    
    }    
    
    /**  
     * 初始化  
     */    
    public void init(Context context) {    
        mContext = context;    
        //获取系统默认的UncaughtException处理器    
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();    
        //设置该CrashHandler为程序的默认处理器    
        Thread.setDefaultUncaughtExceptionHandler(this);    
    }    
    
    /**  
     * 当UncaughtException发生时会转入该函数来处理  
     */    
    @Override    
    public void uncaughtException(Thread thread, Throwable ex) {    
        if (!handleException(ex) && mDefaultHandler != null) {    
            //如果用户没有处理则让系统默认的异常处理器来处理    
            mDefaultHandler.uncaughtException(thread, ex);    
        } else {      //如果自己处理了异常,则不会弹出错误对话框,则需要手动退出app
            try {    
                Thread.sleep(3000);    
            } catch (InterruptedException e) {    
                Log.e(TAG, "error : ", e);    
            }    
            //退出程序    
            android.os.Process.killProcess(android.os.Process.myPid());    
            System.exit(1);    
        }    
    }    
    
    /**  
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.  
     *   
     * @param ex  
     * @return true:如果处理了该异常信息;否则返回false.  
     */    
    private boolean handleException(Throwable ex) {  
        if (ex == null) {    
            return false;    
        }    
        Log.e("error",ex.toString());
        //收集设备参数信息     
        collectDeviceInfo(mContext);    
        
        //使用Toast来显示异常信息    
        new Thread() {    
            @Override    
            public void run() {    
                Looper.prepare();    
                Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_SHORT).show();    
                Looper.loop();    
            }    
        }.start();    
        //保存日志文件     
        saveCatchInfo2File(ex);  
        return true;    
    }    
        
    /**  
     * 收集设备参数信息  
     * @param ctx  
     */    
    public void collectDeviceInfo(Context ctx) {    
        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 + "";    
                infos.put("versionName", versionName);    
                infos.put("versionCode", versionCode);    
            }    
        } catch (NameNotFoundException e) {    
            Log.e(TAG, "an error occured when collect package info", e);    
        }    
        Field[] fields = Build.class.getDeclaredFields();    
        for (Field field : fields) {    
            try {    
                field.setAccessible(true);    
                infos.put(field.getName(), field.get(null).toString());    
                Log.d(TAG, field.getName() + " : " + field.get(null));    
            } catch (Exception e) {    
                Log.e(TAG, "an error occured when collect crash info", e);    
            }    
        }    
    }    
    
    /**  
     * 保存错误信息到文件中  
     *   
     * @param ex  
     * @return  返回文件名称,便于将文件传送到服务器  
     */    
    private String saveCatchInfo2File(Throwable ex) {    
            
        StringBuffer sb = new StringBuffer();    
        for (Map.Entry<String, String> entry : infos.entrySet()) {    
            String key = entry.getKey();    
            String value = entry.getValue();    
            sb.append(key + "=" + value + "\n");    
        }    
            
        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 result = writer.toString();    
        sb.append(result);    
        try {    
            long timestamp = System.currentTimeMillis();    
            String time = formatter.format(new Date());    
            String fileName = "crash-" + time + "-" + timestamp + ".log";    
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {    
                String path = "/mnt/sdcard/crash/";    
                File dir = new File(path);    
                if (!dir.exists()) {    
                    dir.mkdirs();    
                }    
                FileOutputStream fos = new FileOutputStream(path + fileName);    
                fos.write(sb.toString().getBytes());  
                //发送给开发人员
                sendCrashLog2PM(path+fileName);
                fos.close();    
            }    
            return fileName;    
        } catch (Exception e) {    
            Log.e(TAG, "an error occured while writing file...", e);    
        }    
        return null;    
    }    
    
    /**
     * 将捕获的导致崩溃的错误信息发送给开发人员
     * 
     * 目前只将log日志保存在sdcard 和输出到LogCat中,并未发送给后台。
     */
    private void sendCrashLog2PM(String fileName){
        if(!new File(fileName).exists()){
            Toast.makeText(mContext, "日志文件不存在!", Toast.LENGTH_SHORT).show();
            return;
        }
        FileInputStream fis = null;
        BufferedReader reader = null;
        String s = null;
        try {
            fis = new FileInputStream(fileName);
            reader = new BufferedReader(new InputStreamReader(fis, "GBK"));
            while(true){
                s = reader.readLine();
                if(s == null) break;
                //由于目前尚未确定以何种方式发送,所以先打出log日志。
                Log.e("error", s.toString());
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{    // 关闭流
            try {
                reader.close();
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}   
View Code

           或

package com.example.callstatus; 
   
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.PrintWriter; 
import java.io.StringWriter; 
import java.lang.Thread.UncaughtExceptionHandler; 
import java.lang.reflect.Field; 
import java.net.UnknownHostException; 
import java.text.DateFormat; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
import java.util.HashMap; 
import java.util.Map; 
   
import android.annotation.SuppressLint; 
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.Environment; 
import android.os.Looper; 
import android.telephony.TelephonyManager; 
import android.text.TextUtils; 
import android.util.Log; 
import android.widget.Toast; 
   
/**
 * 捕获android程序崩溃日志<br>
 * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序.
 * 
 * @author PMTOAM
 * 
 */ 
@SuppressLint("SimpleDateFormat") 
public class CrashHandler implements UncaughtExceptionHandler 
{ 
   
    public static final String TAG = CrashHandler.class.getCanonicalName(); 
   
    // 系统默认的UncaughtException处理类 
    private Thread.UncaughtExceptionHandler mDefaultHandler; 
    // CrashHandler实例 
    private static CrashHandler INSTANCE = new CrashHandler(); 
    // 程序的Context对象 
    private Context mContext; 
    // 用来存储设备信息和异常信息 
    private Map<String, String> infos = new HashMap<String, String>(); 
   
    // 用于格式化日期,作为日志文件名的一部分 
    private DateFormat formatter = new SimpleDateFormat("yyyyMMdd_HHmmss"); 
   
    /**
     * 保证只有一个实例
     */ 
    private CrashHandler() 
    { 
    } 
   
    /**
     * 获取实例 ,单例模式
     */ 
    public static CrashHandler getInstance() 
    { 
        return INSTANCE; 
    } 
   
    /**
     * 初始化
     * 
     * @param context
     */ 
    public void init(Context context) 
    { 
        mContext = context; 
        // 获取系统默认的UncaughtException处理器 
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); 
        // 设置该CrashHandler为程序的默认处理器 
        Thread.setDefaultUncaughtExceptionHandler(this); 
    } 
   
    /**
     * 当UncaughtException发生时会转入该函数来处理
     */ 
    @Override 
    public void uncaughtException(Thread thread, Throwable ex) 
    { 
        if (!handleException(ex) && mDefaultHandler != null) 
        { 
            // 如果用户没有处理则让系统默认的异常处理器来处理 
            mDefaultHandler.uncaughtException(thread, ex); 
        } 
        else 
        { 
            try 
            { 
                Thread.sleep(3000); 
            } 
            catch (InterruptedException e) 
            { 
                Log.e(TAG, "error : ", e); 
            } 
   
            // 退出程序 
            android.os.Process.killProcess(android.os.Process.myPid()); 
            System.exit(1); 
        } 
    } 
   
    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     * 
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */ 
    private boolean handleException(Throwable ex) 
    { 
        if (ex == null) 
        { 
            return false; 
        } 
   
        // 使用Toast来显示异常信息 
        new Thread() 
        { 
            @Override 
            public void run() 
            { 
                Looper.prepare(); 
                Toast.makeText(mContext, "很抱歉,程序出现异常。", Toast.LENGTH_LONG) 
                        .show(); 
                Looper.loop(); 
            } 
        }.start(); 
   
        // 收集设备参数信息 
        collectDeviceInfo(mContext); 
   
        // 保存日志文件 
        String str = saveCrashInfo2File(ex); 
        Log.e(TAG, str); 
   
        return false; 
    } 
   
    /**
     * 收集设备参数信息
     * 
     * @param ctx
     */ 
    public void collectDeviceInfo(Context ctx) 
    { 
        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 + ""; 
                infos.put("versionName", versionName); 
                infos.put("versionCode", versionCode); 
            } 
   
        } 
        catch (NameNotFoundException e) 
        { 
            Log.e(TAG, "an error occured when collect package info", e); 
        } 
        Field[] fields = Build.class.getDeclaredFields(); 
        for (Field field : fields) 
        { 
            try 
            { 
                field.setAccessible(true); 
                infos.put(field.getName(), field.get(null).toString()); 
                Log.d(TAG, field.getName() + " : " + field.get(null)); 
            } 
            catch (Exception e) 
            { 
                Log.e(TAG, "an error occured when collect crash info", e); 
            } 
        } 
    } 
   
    /**
     * 保存错误信息到文件中
     * 
     * @param ex
     * @return 返回文件名称,便于将文件传送到服务器
     */ 
    private String saveCrashInfo2File(Throwable ex) 
    { 
   
        StringBuffer sb = new StringBuffer(); 
        for (Map.Entry<String, String> entry : infos.entrySet()) 
        { 
            String key = entry.getKey(); 
            String value = entry.getValue(); 
            sb.append("[" + key + ", " + value + "]\n"); 
        } 
   
        sb.append("\n" + getStackTraceString(ex)); 
   
        try 
        { 
            String time = formatter.format(new Date()); 
   
            TelephonyManager mTelephonyMgr = (TelephonyManager) mContext 
                    .getSystemService(Context.TELEPHONY_SERVICE); 
            String imei = mTelephonyMgr.getDeviceId(); 
            if (TextUtils.isEmpty(imei)) 
            { 
                imei = "unknownimei"; 
            } 
   
            String fileName = "CRS_" + time + "_" + imei + ".txt"; 
   
            File sdDir = null; 
   
            if (Environment.getExternalStorageState().equals( 
                    android.os.Environment.MEDIA_MOUNTED)) 
                sdDir = Environment.getExternalStorageDirectory(); 
   
            File cacheDir = new File(sdDir + File.separator + "dPhoneLog"); 
            if (!cacheDir.exists()) 
                cacheDir.mkdir(); 
   
            File filePath = new File(cacheDir + File.separator + fileName); 
   
            FileOutputStream fos = new FileOutputStream(filePath); 
            fos.write(sb.toString().getBytes()); 
            fos.close(); 
   
            return fileName; 
        } 
        catch (Exception e) 
        { 
            Log.e(TAG, "an error occured while writing file...", e); 
        } 
        return null; 
    } 
   
    /**
     * 获取捕捉到的异常的字符串
     */ 
    public static String getStackTraceString(Throwable tr) 
    { 
        if (tr == null) 
        { 
            return ""; 
        } 
   
        Throwable t = tr; 
        while (t != null) 
        { 
            if (t instanceof UnknownHostException) 
            { 
                return ""; 
            } 
            t = t.getCause(); 
        } 
   
        StringWriter sw = new StringWriter(); 
        PrintWriter pw = new PrintWriter(sw); 
        tr.printStackTrace(pw); 
        return sw.toString(); 
    } 
}
View Code

          使用方法

package com.example.callstatus; 
   
import android.app.Application; 
   
public class MyApplication extends Application 
{ 
    @Override 
    public void onCreate() 
    { 
        super.onCreate(); 
           
        CrashHandler crashHandler = CrashHandler.getInstance(); 
        crashHandler.init(getApplicationContext()); 
    } 
}
View Code

          权限

< uses-permission android:name = "android.permission.READ_PHONE_STATE" /> 
< uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" /> 
< uses-permission android:name = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
 
 
 
2GuideActivity.java引导界面:
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import cn.eoe.leigo.splash.adapter.ViewPagerAdapter;

/**
 * 

 * 
 */
public class GuideActivity extends Activity implements OnPageChangeListener {

    private ViewPager vp;
    private ViewPagerAdapter vpAdapter;
    private List<View> views;

    // 底部小点图片
    private ImageView[] dots;

    // 记录当前选中位置
    private int currentIndex;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.guide);

        // 初始化页面
        initViews();

        // 初始化底部小点
        initDots();
    }

    private void initViews() {
        LayoutInflater inflater = LayoutInflater.from(this);

        views = new ArrayList<View>();
        // 初始化引导图片列表
        views.add(inflater.inflate(R.layout.what_new_one, null));
        views.add(inflater.inflate(R.layout.what_new_two, null));
        views.add(inflater.inflate(R.layout.what_new_three, null));
        views.add(inflater.inflate(R.layout.what_new_four, null));

        // 初始化Adapter
        vpAdapter = new ViewPagerAdapter(views, this);
        
        vp = (ViewPager) findViewById(R.id.viewpager);
        vp.setAdapter(vpAdapter);
        // 绑定回调
        vp.setOnPageChangeListener(this);
    }

    private void initDots() {
        LinearLayout ll = (LinearLayout) findViewById(R.id.ll);

        dots = new ImageView[views.size()];

        // 循环取得小点图片
        for (int i = 0; i < views.size(); i++) {
            dots[i] = (ImageView) ll.getChildAt(i);
            dots[i].setEnabled(true);// 都设为灰色
        }

        currentIndex = 0;
        dots[currentIndex].setEnabled(false);// 设置为白色,即选中状态
    }

    private void setCurrentDot(int position) {
        if (position < 0 || position > views.size() - 1
                || currentIndex == position) {
            return;
        }

        dots[position].setEnabled(false);
        dots[currentIndex].setEnabled(true);

        currentIndex = position;
    }

    // 当滑动状态改变时调用
    @Override
    public void onPageScrollStateChanged(int arg0) {
    }

    // 当当前页面被滑动时调用
    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
    }

    // 当新的页面被选中时调用
    @Override
    public void onPageSelected(int arg0) {
        // 设置底部小点选中状态
        setCurrentDot(arg0);
    }

}
View Code

ViewPagerAdapter.java。ViewPager的适配器:

import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import cn.eoe.leigo.splash.MainActivity;
import cn.eoe.leigo.splash.R;

/**
 */
public class ViewPagerAdapter extends PagerAdapter {

    // 界面列表
    private List<View> views;
    private Activity activity;
    private static final String SHAREDPREFERENCES_NAME = "first_pref";
    public ViewPagerAdapter(List<View> views, Activity activity) {
        this.views = views;
        this.activity = activity;
    }

    // 销毁arg1位置的界面
    @Override
    public void destroyItem(View arg0, int arg1, Object arg2) {
        ((ViewPager) arg0).removeView(views.get(arg1));
    }

    @Override
    public void finishUpdate(View arg0) {
    }

    // 获得当前界面数
    @Override
    public int getCount() {
        if (views != null) {
            return views.size();
        }
        return 0;
    }

    // 初始化arg1位置的界面
    @Override
    public Object instantiateItem(View arg0, int arg1) {
        ((ViewPager) arg0).addView(views.get(arg1), 0);
        if (arg1 == views.size() - 1) {
            ImageView mStartWeiboImageButton = (ImageView) arg0
                    .findViewById(R.id.iv_start_weibo);
            mStartWeiboImageButton.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    // 设置已经引导
                    setGuided();
                    goHome();

                }

            });
        }
        return views.get(arg1);
    }

    private void goHome() {
        // 跳转
        Intent intent = new Intent(activity, MainActivity.class);
        activity.startActivity(intent);
        activity.finish();
    }
    /**
     * 
     * method desc:设置已经引导过了,下次启动不用再次引导
     */
    private void setGuided() {
        SharedPreferences preferences = activity.getSharedPreferences(
                SHAREDPREFERENCES_NAME, Context.MODE_PRIVATE);
        Editor editor = preferences.edit();
        // 存入数据
        editor.putBoolean("isFirstIn", false);
        // 提交修改
        editor.commit();
    }

    // 判断是否由对象生成界面
    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return (arg0 == arg1);
    }

    @Override
    public void restoreState(Parcelable arg0, ClassLoader arg1) {
    }

    @Override
    public Parcelable saveState() {
        return null;
    }

    @Override
    public void startUpdate(View arg0) {
    }

}
View Code

SplashActivity.java,欢迎界面。

 

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

/**

 */
public class SplashActivity extends Activity {
    boolean isFirstIn = false;

    private static final int GO_HOME = 1000;
    private static final int GO_GUIDE = 1001;
    // 延迟3秒
    private static final long SPLASH_DELAY_MILLIS = 3000;

    private static final String SHAREDPREFERENCES_NAME = "first_pref";

    /**
     * Handler:跳转到不同界面
     */
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case GO_HOME:
                goHome();
                break;
            case GO_GUIDE:
                goGuide();
                break;
            }
            super.handleMessage(msg);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash);

        init();
    }

    private void init() {
        // 读取SharedPreferences中需要的数据
        // 使用SharedPreferences来记录程序的使用次数
        SharedPreferences preferences = getSharedPreferences(
                SHAREDPREFERENCES_NAME, MODE_PRIVATE);

        // 取得相应的值,如果没有该值,说明还未写入,用true作为默认值
        isFirstIn = preferences.getBoolean("isFirstIn", true);

        // 判断程序与第几次运行,如果是第一次运行则跳转到引导界面,否则跳转到主界面
        if (!isFirstIn) {
            // 使用Handler的postDelayed方法,3秒后执行跳转到MainActivity
            mHandler.sendEmptyMessageDelayed(GO_HOME, SPLASH_DELAY_MILLIS);
        } else {
            mHandler.sendEmptyMessageDelayed(GO_GUIDE, SPLASH_DELAY_MILLIS);
        }

    }

    private void goHome() {
        Intent intent = new Intent(SplashActivity.this, MainActivity.class);
        SplashActivity.this.startActivity(intent);
        SplashActivity.this.finish();
    }

    private void goGuide() {
        Intent intent = new Intent(SplashActivity.this, GuideActivity.class);
        SplashActivity.this.startActivity(intent);
        SplashActivity.this.finish();
    }
}
View Code

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值