mirror of
				https://github.com/pierre42100/ComunicAndroid
				synced 2025-10-31 01:24:43 +00:00 
			
		
		
		
	Imported CrashReporter.
This commit is contained in:
		| @@ -18,6 +18,10 @@ android { | ||||
|             buildConfigField "String", "api_url", "\"http://devweb.local/comunic/api/\"" | ||||
|             buildConfigField "String", "api_service_name", "\"ComunicAndroid\"" | ||||
|             buildConfigField "String", "api_service_token", "\"5eQ8WGAeDTTyY\"" | ||||
|  | ||||
|             //Connexion to Crash Reporter | ||||
|             buildConfigField "String", "crash_reporter_url", "\"http://devweb.local/CrashReporterWeb/project/api/v1/push\"" | ||||
|             buildConfigField "String", "crash_reporter_key", "\"KSyqOzkfJasDTxE0wrXYnUPl8dV1veBc\"" | ||||
|         } | ||||
|  | ||||
|         release { | ||||
| @@ -28,6 +32,10 @@ android { | ||||
|             buildConfigField "String", "api_url", "\"https://api.communiquons.org/\"" | ||||
|             buildConfigField "String", "api_service_name", "\"ComunicAndroid\"" | ||||
|             buildConfigField "String", "api_service_token", "\"cWHlmMS5A1\"" | ||||
|  | ||||
|             //Connexion to Crash Reporter | ||||
|             buildConfigField "String", "crash_reporter_url", "\"https://crashreporter.communiquons.org/api/v1/push\"" | ||||
|             buildConfigField "String", "crash_reporter_key", "\"z38jtULRuKHb2BOyvG4VTXDhn9gwelZ1\"" | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,396 @@ | ||||
| package org.communiquons.android.comunic.client.crashreporter; | ||||
|  | ||||
| import android.content.Context; | ||||
| import android.os.AsyncTask; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.support.annotation.UiThread; | ||||
| import android.util.Log; | ||||
|  | ||||
| import org.communiquons.android.comunic.client.BuildConfig; | ||||
|  | ||||
| import java.io.BufferedOutputStream; | ||||
| import java.io.BufferedReader; | ||||
| import java.io.BufferedWriter; | ||||
| import java.io.File; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.FileOutputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | ||||
| import java.io.OutputStream; | ||||
| import java.io.OutputStreamWriter; | ||||
| import java.net.HttpURLConnection; | ||||
| import java.net.URL; | ||||
| import java.net.URLEncoder; | ||||
|  | ||||
| /** | ||||
|  * Crash Reporter library | ||||
|  * | ||||
|  * This library intends to report fatal error to a remote server | ||||
|  * | ||||
|  * Licence : the MIT Licence | ||||
|  * | ||||
|  * @author Pierre HUBERT | ||||
|  * Created by pierre on 4/12/18. | ||||
|  */ | ||||
|  | ||||
| public class CrashReporter implements Thread.UncaughtExceptionHandler { | ||||
|  | ||||
|     /** | ||||
|      * Debug tab | ||||
|      */ | ||||
|     private static final String TAG = "CrashReporter"; | ||||
|  | ||||
|     /** | ||||
|      * Connexion timeout | ||||
|      */ | ||||
|     private static final int API_CONNEXION_TIMEOUT = 3000; | ||||
|  | ||||
|     /** | ||||
|      * Method used to connect to the api | ||||
|      */ | ||||
|     private static final String API_CONNEXION_METHOD = "POST"; | ||||
|  | ||||
|     /** | ||||
|      * Report file name | ||||
|      */ | ||||
|     private static final String REPORT_FILENAME = "crash_report.txt"; | ||||
|  | ||||
|     /** | ||||
|      * Application context | ||||
|      */ | ||||
|     private Context mContext; | ||||
|  | ||||
|     /** | ||||
|      * Default UncaughtExceptionHandler | ||||
|      */ | ||||
|     private Thread.UncaughtExceptionHandler defaultUEH; | ||||
|  | ||||
|     /** | ||||
|      * API URL | ||||
|      */ | ||||
|     private String mApiURL; | ||||
|  | ||||
|     /** | ||||
|      * Application key | ||||
|      */ | ||||
|     private String mAppKey; | ||||
|  | ||||
|     /** | ||||
|      * Construct the library | ||||
|      * | ||||
|      * @param context A valid context (the application context will be stored) | ||||
|      * @param url The URL where the reports have to be uploaded | ||||
|      * @param key The application key | ||||
|      */ | ||||
|     public CrashReporter(Context context, String url, String key){ | ||||
|  | ||||
|         //Set application context and activity references | ||||
|         mContext = context.getApplicationContext(); | ||||
|  | ||||
|         //Save api information | ||||
|         mApiURL = url; | ||||
|         mAppKey = key; | ||||
|  | ||||
|         //Save default thread uncaught exception handler | ||||
|         this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the API URL | ||||
|      * | ||||
|      * @param ApiURL The new API URL | ||||
|      */ | ||||
|     public void setApiURL(String ApiURL) { | ||||
|         this.mApiURL = ApiURL; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the current API URL | ||||
|      * | ||||
|      * @return The current API URL | ||||
|      */ | ||||
|     public String getApiURL() { | ||||
|         return mApiURL; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the application key | ||||
|      * | ||||
|      * @param appKey The application key | ||||
|      */ | ||||
|     public void setAppKey(String appKey) { | ||||
|         this.mAppKey = appKey; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the current application key | ||||
|      * | ||||
|      * @return The application key | ||||
|      */ | ||||
|     public String getAppKey() { | ||||
|         return mAppKey; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Override | ||||
|     public void uncaughtException(Thread t, Throwable e) { | ||||
|  | ||||
|         //Generate the report | ||||
|         String report = generateReport(t, e); | ||||
|         Log.e(TAG, "Generated report: " + report); | ||||
|  | ||||
|         //Try to upload the report | ||||
|         if(!save_report(report)) | ||||
|             Log.e(TAG, "Could not save the report!"); | ||||
|         else | ||||
|             Log.v(TAG, "Report successfully saved for later upload."); | ||||
|  | ||||
|         //Call default exception handler | ||||
|         this.defaultUEH.uncaughtException(t, e); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Generate the crash report | ||||
|      * | ||||
|      * @param t The thread where the exception occurred | ||||
|      * @param e The exception | ||||
|      * @return The report as a string | ||||
|      */ | ||||
|     private String generateReport(Thread t, Throwable e){ | ||||
|  | ||||
|         //Begin report | ||||
|         String report = "Exception: " + e.toString() + "\n\n"; | ||||
|  | ||||
|         //Generic information | ||||
|         report += "Thread name: " + t.getName() + "\n"; | ||||
|         report += "Application ID: " + BuildConfig.APPLICATION_ID +"\n"; | ||||
|         report += "Application version: " + BuildConfig.VERSION_NAME +"\n"; | ||||
|         report += "Code version: " + BuildConfig.VERSION_CODE + "\n\n"; | ||||
|         report += "\n"; | ||||
|  | ||||
|  | ||||
|         //Process stack trace | ||||
|         report += "---------- Stack trace ----------\n"; | ||||
|         report += stackTraceToString(e.getStackTrace()); | ||||
|         report += "---------------------------------\n\n\n"; | ||||
|  | ||||
|  | ||||
|         //Process error cause | ||||
|         report += "------------ Cause --------------\n"; | ||||
|         Throwable cause = e.getCause(); | ||||
|         if(cause != null){ | ||||
|             report += cause.getMessage() + "\n"; | ||||
|             report += stackTraceToString(cause.getStackTrace()); | ||||
|         } | ||||
|         else | ||||
|             report += "No data available.\n"; | ||||
|         report += "---------------------------------\n"; | ||||
|  | ||||
|         return report; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Turn a stack trace array into a string | ||||
|      * | ||||
|      * @param array The array to convert | ||||
|      * @return Generated string | ||||
|      */ | ||||
|     private String stackTraceToString(StackTraceElement[] array){ | ||||
|         String string = ""; | ||||
|         for(StackTraceElement el : array){ | ||||
|             string += el.toString() + "\n"; | ||||
|         } | ||||
|         return string; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Asynchronously upload a report to the server | ||||
|      */ | ||||
|     @UiThread | ||||
|     public void uploadAwaitingReport(){ | ||||
|  | ||||
|         new AsyncTask<Void, Void, Void>(){ | ||||
|  | ||||
|             @Override | ||||
|             protected Void doInBackground(Void... params) { | ||||
|                 async_upload(); | ||||
|                 return null; | ||||
|             } | ||||
|  | ||||
|         }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Push online any awaiting report | ||||
|      */ | ||||
|     private void async_upload(){ | ||||
|  | ||||
|         //Get the report file | ||||
|         File file = get_report_file(false); | ||||
|  | ||||
|         //Check if the file exists or not | ||||
|         if(file == null){ | ||||
|             Log.v(TAG, "Report file seems not to exists."); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         //Get report content | ||||
|         String report; | ||||
|         try { | ||||
|             report = readIs(new FileInputStream(file)); | ||||
|  | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         //Launch report upload | ||||
|         if(!upload(report)) | ||||
|             Log.e(TAG, "An error occurred while trying to upload report!"); | ||||
|         else | ||||
|             Log.v(TAG, "The report has been successfully uploaded:"); | ||||
|  | ||||
|         //Delete the awaiting report | ||||
|         if(!file.delete()){ | ||||
|             Log.e(TAG, "An error occurred while trying to delete report file !"); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Intend to upload the report online | ||||
|      * | ||||
|      * @param report The report to upload | ||||
|      * @return TRUE in case of success / FALSE else | ||||
|      */ | ||||
|     private boolean upload(String report){ | ||||
|  | ||||
|         try { | ||||
|  | ||||
|             //Prepare the request body | ||||
|             String requestBody = "app_key=" + URLEncoder.encode(mAppKey, "UTF-8") | ||||
|                     + "&report=" + report; | ||||
|  | ||||
|             //Prepare the connexion | ||||
|             URL url = new URL(mApiURL); | ||||
|  | ||||
|             //Open URL connection | ||||
|             HttpURLConnection conn = (HttpURLConnection) url.openConnection(); | ||||
|  | ||||
|             //Setup a few settings | ||||
|             conn.setRequestMethod(API_CONNEXION_METHOD); | ||||
|             conn.setDoOutput(true); | ||||
|             conn.setDoInput(false); | ||||
|             conn.setConnectTimeout(API_CONNEXION_TIMEOUT); | ||||
|             conn.setChunkedStreamingMode(0); | ||||
|  | ||||
|             //Connect to the server | ||||
|             conn.connect(); | ||||
|  | ||||
|             //Write report | ||||
|             OutputStream os = new BufferedOutputStream(conn.getOutputStream()); | ||||
|             BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")); | ||||
|             writer.write(requestBody); | ||||
|             writer.flush(); | ||||
|             writer.close(); | ||||
|             os.close(); | ||||
|  | ||||
|             conn.disconnect(); | ||||
|  | ||||
|             //Success | ||||
|             return true; | ||||
|  | ||||
|         } catch (java.io.IOException e) { | ||||
|             e.printStackTrace(); | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Save the report locally for ulterior upload | ||||
|      * | ||||
|      * @param report The report to save | ||||
|      * @return TRUE for a success / FALSE else | ||||
|      */ | ||||
|     private boolean save_report(String report){ | ||||
|  | ||||
|         //Get the file | ||||
|         File file = get_report_file(true); | ||||
|  | ||||
|         //Check for error | ||||
|         if(file == null){ | ||||
|             Log.e(TAG, "Could not create report file!"); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         try { | ||||
|  | ||||
|             //Open the file for writing | ||||
|             OutputStream os = new BufferedOutputStream(new FileOutputStream(file, false)); | ||||
|             BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")); | ||||
|             writer.write(URLEncoder.encode(report, "UTF-8")); | ||||
|             writer.flush(); | ||||
|             writer.close(); | ||||
|             os.close(); | ||||
|  | ||||
|  | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         //Success | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the saved report file | ||||
|      * | ||||
|      * @param create Create the file if does not exists | ||||
|      * @return The report file (null in case of failure) | ||||
|      */ | ||||
|     @Nullable | ||||
|     private File get_report_file(boolean create){ | ||||
|         File file = new File(mContext.getCacheDir(), REPORT_FILENAME); | ||||
|  | ||||
|         //Check file existence | ||||
|         if(!file.exists()){ | ||||
|  | ||||
|             //Check if the file can be created | ||||
|             if(create) { | ||||
|                 try { | ||||
|                     //Intend to create the file | ||||
|                     if (!file.createNewFile()) | ||||
|                         return null; | ||||
|                 } catch (IOException e) { | ||||
|                     e.printStackTrace(); | ||||
|                     return null; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|                 return null; | ||||
|         } | ||||
|  | ||||
|         return file; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Read an input stream into a string | ||||
|      * | ||||
|      * @param is The input stream to read | ||||
|      * @return Read string | ||||
|      */ | ||||
|     private String readIs(InputStream is) throws IOException { | ||||
|         BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is, "UTF-8")); | ||||
|         StringBuilder out = new StringBuilder(); | ||||
|         String line; | ||||
|         while((line = bufferedReader.readLine()) != null) | ||||
|             out.append(line); | ||||
|         bufferedReader.close(); | ||||
|         return out.toString(); | ||||
|     } | ||||
| } | ||||
| @@ -15,7 +15,9 @@ import android.view.Menu; | ||||
| import android.view.MenuItem; | ||||
| import android.widget.Toast; | ||||
|  | ||||
| import org.communiquons.android.comunic.client.BuildConfig; | ||||
| import org.communiquons.android.comunic.client.R; | ||||
| import org.communiquons.android.comunic.client.crashreporter.CrashReporter; | ||||
| import org.communiquons.android.comunic.client.data.helpers.APIRequestHelper; | ||||
| import org.communiquons.android.comunic.client.data.helpers.AccountHelper; | ||||
| import org.communiquons.android.comunic.client.data.utils.AccountUtils; | ||||
| @@ -87,6 +89,12 @@ public class MainActivity extends AppCompatActivity implements openConversationL | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|  | ||||
|         //Initialize crash reporter | ||||
|         CrashReporter reporter = new CrashReporter(this, BuildConfig.crash_reporter_url, | ||||
|                 BuildConfig.crash_reporter_key); | ||||
|         reporter.uploadAwaitingReport(); | ||||
|         Thread.setDefaultUncaughtExceptionHandler(reporter); | ||||
|  | ||||
|         //Initialize account objects | ||||
|         accountHelper = new AccountHelper(this); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Pierre
					Pierre