2013-07-18 33 views
1

我使用LogCat获取有关我的Android应用程序执行的反馈,当它通过我的eclipse模拟器运行时。Android LogCat文件位置并发送电子邮件副本

apk在我的一部真实手机上运行时,我收到了一些不同的行为......我很好奇LogCat是否在手机的某个位置生成了一个文件,我也可以访问它。

最终我想获得LogCat结果并通过支持电子邮件地址将它们发送给我自己。目的是让有问题的用户在发生问题时向我发送LogCat结果的副本。

如果LogCat创建一个我可以访问的文件以及如何通过电子邮件发送给我自己的任何信息,将不胜感激。如果LogCat不这样做,那么任何建议在另一种方式做到这一点将不胜感激。

+0

为了澄清,我看到在http如何与亚洲开发银行这样做参考://stackoverflow.com/questions/4424544/where-are-android-logcat-files-stored但是有没有办法在生产中打开它并获取有关信息? –

+1

“如果LogCat没有这样做,那么有关替代方式的任何建议将不胜感激。” - 使用ACRA:http://acra.ch/,结合使用LogCat以外的自己的日志记录。 – CommonsWare

回答

0

非常艰巨的任务,但希望这将有助于...

(做大量的复制/粘贴的,所以请让我知道如果我错过了一些重要的代码!我没有测试最大1MB的设置 - 也可能是有道理的把它放在MainActivity.onCreate(),所以我们不会把它称为永远的日志消息,但这个工程...)

一些这从LogCollector,所以给信用在哪里信用:(https://code.google.com/p/android-log-collector/

从我的LogCollector类的相关方法:(需要明显的输入和电子邮件多个附件o f日志,如果两者都存在 - 我有一个选项来启用日志文件以及logcat。 BTW,logcat的有〜64KB的内存,所以你不会从该获得多少记录,因此需要为我记录到一个文件)

public boolean sendLog(String email, String subject, String body) { 
    Logger.v("LogCollector - sendLog()"); 
    ArrayList<String> lines = mLastLogs; 
    if (lines.size() > 0) { 
     Uri emailUri = Uri.parse("mailto:" + email); 
     ///////////////////////////////////////////////////////////////////////////////////////  
     // Create and open folder for output file 
     Logger.d("LogCollector - Creating folder & file..."); 
     final String filename = "AppName_logCat.txt"; 
     File folder = new File(Environment.getExternalStorageDirectory()+"/temp/"); 
     // Create directory structure if needed 
     if(folder.mkdirs()){ 
      Logger.v("Created temp folder."); 
     }else{ 
      Logger.v("Did NOT create temp folder - perhaps it already exists"); 
     } 
     //Create log file 
     File logFile = new File(Environment.getExternalStorageDirectory()+"/temp/", filename); 
     Logger.v("Log File Path: "+logFile.getAbsolutePath()); 
     FileWriter fileWriter; 
     //String phoneInfo = collectPhoneInfo(); 
     //String appInfo = collectAppInfo(); 
     //Put contents into log file, including phone info 
     try { 
      Logger.d("LogCollector - Putting info into log file..."); 
      fileWriter = new FileWriter(logFile, false);  //dont append, clear first 
      BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); 
      //bufferedWriter.write(phoneInfo); 
      //bufferedWriter.write("\n\n"); 
      //bufferedWriter.write(appInfo); 
      bufferedWriter.write("\n\n"); 
      for (String line : lines) { 
        bufferedWriter.write(line); 
        bufferedWriter.newLine(); 
      } 
      bufferedWriter.close(); 
     } catch (IOException e1) { 
      Logger.w("LogCollector - Error putting log info into file: "+e1); 
      if(!android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { 
       Logger.w("SD card not present or not accessible"); 
      } 
      return false; 
     } 
     // Check if log can be read for debugging 
     if(!logFile.canRead()){ 
      Logger.e("Can't read file!"); 
      return false; 
     } 
     // Create appLogFile objects 
     appLogFile = new File(Environment.getExternalStorageDirectory()+"/temp/", appFilename); 

     //Send log file via email 
     Logger.d("LogCollector - Emailing Logs..."); 
     // Need to assemble body this way due to Android bug 
     //emailIntent.putExtra(Intent.EXTRA_TEXT, body);      //Regular method - Causes warning 
     //ArrayList<String> extra_text = new ArrayList<String>();    //workaround 
     //extra_text.add("See attached CSV files.");       //workaround 
     //emailIntent.putStringArrayListExtra(Intent.EXTRA_TEXT, extra_text); //causes no error but missing body/text - not a big deal, but pointless to have if doesnt issue a body 
     // Put info in email 
     Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); 
     emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{emailUri.toString()}); 
     emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject); 
     emailIntent.setType("text/plain"); 
     ArrayList<Uri> uris = new ArrayList<Uri>();  
     String[] filePaths;    
     // If appLogFile exists & is valid, attach to email 
     if(appLogFile.exists() && appLogFile.isFile() && appLogFile.canRead()) { 
      Logger.i("appLogFile exists; attaching to email"); 
      filePaths = new String[] {logFile.toString(),appLogFile.toString()}; 
     }else{ 
      Logger.w("Error finding or reading logfile. Debug disabled?!"); 
      filePaths = new String[] {logFile.toString()}; 
     } 
     for (String file : filePaths) { 
      File fileIn = new File(file); 
      Uri u = Uri.fromFile(fileIn); 
      uris.add(u); 
     } 
     emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); 
     mContext.startActivity(Intent.createChooser(emailIntent, "Email Logs to Developer")); 
    } 
    return true; 
} 

自定义logger类:(处理我所有的日志 - 写入文件以及如果调试选项被激活)

public class Logger { 
private static final String TAG = "AppName"; 
private static final int MAX_FILESIZE=1; //in MB 
private static File logFolder; 
private static File logFile; 
private static String filename = TAG+"_logfile.txt"; 
private static FileWriter fileWriter; 
private static BufferedWriter bufferedWriter; 
private static SimpleDateFormat sdf; 
private static String dateTime; 
private static int PID; 
private static int TID; 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
public static void v(String message) { 
    // Do normal logging to logcat 
    Log.v(TAG,message); 
    // Log to file 
    if(MainActivity.enable_debug()) { 
     PID= android.os.Process.myPid(); 
     TID=android.os.Process.myTid(); 
     logToFile(PID,TID,"V",message); 
    } 
} 

public static void d(String message) { 
    // Do normal logging to logcat 
    Log.d(TAG,message); 
    // Log to file 
    if(MainActivity.enable_debug()) { 
     PID= android.os.Process.myPid(); 
     TID=android.os.Process.myTid(); 
     logToFile(PID,TID,"D",message); 
    } 
} 
public static void i(String message) { 
    // Do normal logging to logcat 
    Log.i(TAG,message); 
    // Log to file 
    if(MainActivity.enable_debug()) { 
     PID= android.os.Process.myPid(); 
     TID=android.os.Process.myTid(); 
     logToFile(PID,TID,"I",message); 
    } 
} 
public static void w(String message) { 
    // Do normal logging to logcat 
    Log.w(TAG,message); 
    // Log to file 
    if(MainActivity.enable_debug()) { 
     PID= android.os.Process.myPid(); 
     TID=android.os.Process.myTid(); 
     logToFile(PID,TID,"W",message); 
    } 
} 
public static void e(String message) { 
    // Do normal logging to logcat 
    Log.e(TAG,message); 
    // Log to file 
    if(MainActivity.enable_debug()) { 
     PID= android.os.Process.myPid(); 
     TID=android.os.Process.myTid(); 
     logToFile(PID,TID,"E",message); 
    } 
} 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
@SuppressLint("SimpleDateFormat") 
private static void logToFile(int PID,int TID,String LEVEL,String message) { 
    //return if there is no SD card, or it's inaccessible 
    if(!android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { 
     return; 
    } 
    // Date - Time - PID - TID - LEVEL - TAG? - Message 
    // Create and initialize temp folder for log file if doesn't already exist  
    if(logFolder == null) { 
     logFolder = new File(Environment.getExternalStorageDirectory()+"/temp/"); 
    } 
    // Create temp folder if doesn't exist 
    if(!logFolder.exists()) { 
     //Logger.i("Creating temp folder on SD card root..."); 
     logFolder.mkdirs(); 
    } 
    // Create log file if doesn't already exist 
    if(logFile == null) { 
     logFile = new File(Environment.getExternalStorageDirectory()+"/temp/", filename); 
     try { 
      logFile.createNewFile(); 
     } catch (IOException e) { 
      Logger.e("Error creating new file: "+e); 
     } 
    } 
    // Check log file validity - Error if there's a problem with the file 
    // Not sure if this is a performance hit 
    if(!logFile.exists() || !logFile.isFile() || !logFile.canRead()) { 
     //Logger.e("Problem with logFile! Doesnt exist, isn't a file, or can't read it"); 
     return; 
    } 
    //Get Date/Time 
    if(sdf == null) { 
     sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss"); //determines dateTime format 
    } 
    dateTime = sdf.format(new Date()); //set to current date/time 

    // Write log message to file 
    try { 
     if(fileWriter == null) { 
      //if(size of file is > 1MB or whatever, then set below to false to clear file first? Or need to do something better so we dont wipe mid incoming text) { 
      if(logFile.length() > MAX_FILESIZE*1024*1024) { 
       Logger.i("logFile is > "+MAX_FILESIZE+" MB, clearing first..."); 
       fileWriter = new FileWriter(logFile, false);  // true=dont append, clear first 
      }else{ 
       fileWriter = new FileWriter(logFile, true);   // false=append, clear first 
      } 
     } 
     if(bufferedWriter == null) { 
      bufferedWriter = new BufferedWriter(fileWriter); 
     } 
     bufferedWriter.write(dateTime+" "+PID+" "+TID+" "+LEVEL+" "+TAG+": "+message); //write line to log file 
     bufferedWriter.newLine(); 
     bufferedWriter.flush();  //forces to write to file? 
    } catch (IOException e) { 
     Logger.e("Error writing to log: "); 
     e.printStackTrace(); 
    }   
} 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

}

从我的公用事业类重要的方法:

// EMAIL LOGS 
public static void emailLogsDialog(final Context context) { 
    final AlertDialog.Builder builder = new AlertDialog.Builder(context); 
    builder.setTitle("Send Logs to Developer"); 
    builder.setMessage("Do you want to send your system logs to the Developer for troubleshooting?\n\nWarning: The logs may contain personal information; this is beyond the Developer's control."); 
    builder.setInverseBackgroundForced(true); 
    builder.setPositiveButton("Ok",new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog,int which) { 
      dialog.dismiss(); 
      emailLogs(context); 
     } 
    }); 
    builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog,int which) { 
      dialog.dismiss(); 
     } 
    }); 
    AlertDialog alertConfirm = builder.create(); 
    alertConfirm.show(); 
} 
public static void emailLogs(final Context context) { 
    final LogCollector logCollector = new LogCollector(context); 
    final AlertDialog.Builder builder = new AlertDialog.Builder(context); 
    new AsyncTask<Void, Void, Boolean>() { 
     AlertDialog alert; 
     @Override 
     protected Boolean doInBackground(Void... params) { 
      return logCollector.collect(); 
     } 
     @Override 
     protected void onPreExecute() { 
      builder.setTitle("Send Logs to Developer"); 
      builder.setMessage("Collecting Logs & Emailing now..."); 
      builder.setInverseBackgroundForced(true); 
      builder.setNegativeButton("Cancel", 
        new DialogInterface.OnClickListener() { 
         @Override 
         public void onClick(DialogInterface dialog,int which) { 
          dialog.dismiss(); 
          return; 
         } 
        }); 
      alert = builder.create(); 
      alert.show(); 
     } 
     @Override 
     protected void onPostExecute(Boolean result) { 
      alert.dismiss(); 
      builder.setTitle("Send Logs to Developer"); 
      builder.setMessage("Logs successfully sent to Developer\n\n (Make sure your email app successfully sent the email.)"); 
      builder.setInverseBackgroundForced(true); 
      builder.setPositiveButton("Ok", 
        new DialogInterface.OnClickListener() { 
         @Override 
         public void onClick(DialogInterface dialog,int which) { 
          dialog.dismiss(); 
         } 
        }); 
      if (result) { 
       Logger.d("Successfully extracted logs."); 
       if(logCollector.sendLog("[email protected]", "OnCallPager Error Log", "Error Log\n")) { 
        Toast.makeText(context,"Logs successfully extracted to your default email application",Toast.LENGTH_LONG).show(); 
       }else{ 
        Toast.makeText(context,"There was a problem extracting the logs.\n\nDo you have an SD card and is it mounted?",Toast.LENGTH_LONG).show(); 
       } 
      }else{ 
       Logger.e("Failed to extract logs!"); 
       Toast.makeText(context,"Error acquiring logs!",Toast.LENGTH_LONG).show(); 
      } 
     }  
    }.execute(); 
} 

通话记录是这样的:

Logger.v("LogCollector - sendLog()"); 

关键sendEmail(原木):(如上使用)

if(logCollector.sendLog("[email protected]", "OnCallPager Error Log", "Error Log\n")) { 
       Toast.makeText(context,"Logs successfully extracted to your default email application",Toast.LENGTH_LONG).show(); 
      }else{ 
       Toast.makeText(context,"There was a problem extracting the logs.\n\nDo you have an SD card and is it mounted?",Toast.LENGTH_LONG).show(); 
      } 
相关问题