一分钟解决Android日志打印在手机资源文件中问题

在很多Android应用开发中都有遇到编写好的程序在公测时出现闪退问题,但是自己在调试时又不好复现。故而耽误应用错误查不出来,耽误产品发布和更新。于是大多数APP都有自己的logcat打印日志到自己应用目录下以便自己开发人员的调试更改。闲言少续,咱们步入正题。

第一步,当然是加入读写权限了。代码如下:

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

当然也可以动态申请:在mian函数中加入下列代码

 try {
            //检测是否有写的权限
            int permission = ActivityCompat.checkSelfPermission(MainActivity.this,
                    "android.permission.WRITE_EXTERNAL_STORAGE");
            if (permission != PackageManager.PERMISSION_GRANTED) {
                // 没有写的权限,去申请写的权限,会弹出对话框
                ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS_STORAGE,1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

第二步,

就是建一个MyCrashHandler类,用来继承谷歌官方封装好的 UncaughtExceptionHandler(当一个线程由于未捕获异常即将终止时,Java虚拟机将使用thread . getuncaughtexceptionhandler()查询线程的uncaughtException处理程序,并调用处理程序的uncaughtException方法,将线程和异常作为参数传递。如果一个线程没有显式地设置它的UncaughtExceptionHandler,那么它的ThreadGroup对象就充当它的UncaughtExceptionHandler。如果ThreadGroup对象没有处理异常的特殊要求,它可以将调用转发给默认的未捕获异常处理程序),用一句话概括UncaughtExceptionHandler:用于处理未捕获异常突然终止时调用的处理程序的接口。代码如下:

import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Date;


/**
 * 全局捕获导常,保存到本地错误日志。日志
 * 路径位于sdcard/错误日志Log/myErrorLog下。
 */
public class MyCrashHandler implements UncaughtExceptionHandler {

    private  String logPath;
    private static MyCrashHandler instance;
    private Context ctc= null;

    public static MyCrashHandler getInstance() {
        if (instance == null) {
            instance = new MyCrashHandler();
        }
        return instance;
    }

    public void init(Context ctx) {
        ctc = ctx;

        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 核心方法,当程序crash 会回调此方法, Throwable中存放这错误日志
     * UncaughtExceptionHandler自带发生错误回调函数
     * arg0.toString代表线程信息
     * arg1.getMessage()代表错误信息
     */
    @Override
    public void uncaughtException(Thread arg0, Throwable arg1) {
        String state = Environment.getExternalStorageState();
		if (state.equals(Environment.MEDIA_MOUNTED)) {
			    logPath =  Environment.getExternalStorageDirectory().getAbsolutePath();
			    WriteDataToStorage(arg1.getMessage(), logPath, 3, 0);
		}
    }


    /**
     * @param content:    要写的内容
     * @param filedirname 文件夹的名字
     * @param mode:       以什么方式往里面去写 0 1 2 3
     * @param ways:       两种方式 Buffer RandomAccessFile  Print  0 1 2
     * @Function: 将content写到指定的文件的指定的目录下去
     * @Return:
     */
    private void WriteDataToStorage(String content, String filedirname, int mode, int ways) {
//        String FileName = filedirname + File.separator + filename;   //拼接字符串  文件的存储路径
        File f = new File(logPath);
        File subfile = new File(f, "myLog" + ".txt");  //文件夹路径和文件路径   判断文件是否存在
        if (subfile.exists()) {
            subfile.setWritable(true);
            boolean readable = subfile.canRead();
            boolean writeable = subfile.canWrite();
            System.out.println("文件创建成功" + "readable:" + readable + " writeable:" + writeable);
        } else {
            try {
                subfile.createNewFile();
            } catch (IOException e) {
                System.out.println("文件创建出错  " + e.getMessage());
                e.printStackTrace();
            }
        }
        int Context_Mode = mode;
        int Ways = ways;
        if (Context_Mode == 0) {
            Context_Mode = Context.MODE_PRIVATE;  //该文件只能被当前程序读写。
        } else if (Context_Mode == 1) {
            Context_Mode = Context.MODE_APPEND;   //以追加方式打开该文件,应用程序可以向该文件中追加内容。
        } else if (Context_Mode == 2) {
            Context_Mode = Context.MODE_WORLD_READABLE;  //该文件的内容可以被其他应用程序读取。
        } else if (Context_Mode == 3) {
            Context_Mode = Context.MODE_WORLD_WRITEABLE;  //该文件的内容可由其他程序读、写。
        } else {
            Context_Mode = Context.MODE_WORLD_WRITEABLE;  // 反正都可以读
        }
        if (Ways == 0) {
            System.out.println( "BufferWriter");
            FileOutputStream fileOutputStream = null;
            BufferedWriter bufferedWriter = null;
            OutputStreamWriter outputStreamWriter = null;
            try {
                //fileOutputStream = openFileOutput(FileName, Context_Mode);  contains a path separator 报错
                fileOutputStream = new FileOutputStream(subfile);
//                bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream, "utf-8"));  //解决输入中文的问题
//                bufferedWriter.write(content + "\t");
//                bufferedWriter.flush();
//                bufferedWriter.close();
                System.out.println("======================================");
                outputStreamWriter = new OutputStreamWriter(fileOutputStream, "utf-8");   //两种方式都可以
                outputStreamWriter.write(content);
                outputStreamWriter.flush();
                outputStreamWriter.close();
                ListFileDirName(Environment.getExternalStorageDirectory().getAbsolutePath());
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("写入数据出错 " + e.getMessage());
            } finally {
                if (bufferedWriter != null) {
                    try {
                        bufferedWriter.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } else if (Ways == 1) {
            System.out.println("RandomAccessFile");
            try {
                RandomAccessFile raf = new RandomAccessFile(subfile, "rw");
                raf.seek(subfile.length());
                raf.write(content.getBytes());
                raf.close();
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("写入数据出错 " + e.getMessage());
            }
        } else if (Ways == 2) {
            System.out.println("Printer");
            try {
                FileOutputStream fileoutputStream = new FileOutputStream(subfile);
                //openFileOutput("text2", Context.MODE_PRIVATE);
                PrintStream ps = new PrintStream(fileoutputStream);
                ps.print(content + "\t");
                ps.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        } else
            Ways = 0;
    }

//遍历当前目录下的所有文件
    private File[] ListFileDirName(String fileDirName) {
        File fileDir = new File(fileDirName);
        File[] files = new File[0];
        if (fileDir.isDirectory()) {
            files = fileDir.listFiles();
        }

        for (File a : files) {   //可以利用适配器做成界面  完成为了玩没意思
//            System.out.println("==========++++====="+ a.toString());
            String result=null;
            if(a.toString().equals("/storage/emulated/0/myLog.txt")) {
            //这里可以放将文件上传到服务器的函数
                try {
                    File f = new File(a.toString());
                    int length = (int) f.length();
                    byte[] buff = new byte[length];
                    FileInputStream fin = new FileInputStream(f);
                    fin.read(buff);
                    fin.close();
                    result = new String(buff, "UTF-8");
                } catch (Exception e) {
                    e.printStackTrace();
                    Toast.makeText(ctc, "没有找到指定文件", Toast.LENGTH_SHORT).show();
                }
            }
        }
        return files;
    }
}

第三步:在主函数中调用MyCrashHandler函数

 MyCrashHandler myCrashHandler = MyCrashHandler.getInstance();
 myCrashHandler.init(getApplicationContext());

以上就是打印错误日志的全部代码。其实还有一点值得注意的就是保存日志文件路径时有的人用:getApplicationContext().getFilesDir().getAbsolutePath()+ File.separator。而我这里用的是:
Environment.getExternalStorageDirectory().getAbsolutePath();
这里最大的区别就是上面的是保存到手机内存中的,下面是保存到手机外存中的。这里的手机外存不是以前那种插黑色SD那种,而是手机自带的外部储存。通俗理解就是现在手机将以前拔插的Sd储存卡内置到手机中了。
只有储存到外存中你才可以在手机资源管理器查看,内存中在一般情况下看不到的。

到这里就结束了,希望帮助你顺利脱坑,请结合自己实际代码进行调试。
希望能够帮到大家哦!IT需要爱与和平😊,最后请大家关注我,以及我的一分钟系列(Android篇和小程序篇)让你一分钟实现相应的功能,成功引起产品经理的注意袄。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值