NewPipe/app/src/main/java/org/schabi/newpipe/ErrorActivity.java

425 lines
15 KiB
Java
Raw Normal View History

2016-02-25 22:02:42 +01:00
2016-02-25 23:19:43 +01:00
package org.schabi.newpipe;
2016-02-25 22:02:42 +01:00
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
2016-02-29 21:21:15 +01:00
import android.graphics.Color;
2016-02-25 23:19:43 +01:00
import android.net.Uri;
2016-02-25 22:02:42 +01:00
import android.os.Build;
import android.preference.PreferenceManager;
import android.support.design.widget.Snackbar;
import android.support.v4.app.NavUtils;
2016-05-25 23:51:22 +02:00
import android.support.v7.app.ActionBar;
2016-02-25 22:02:42 +01:00
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
2016-02-25 23:19:43 +01:00
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
2016-02-25 22:02:42 +01:00
import android.view.MenuItem;
import android.view.View;
2016-02-25 23:19:43 +01:00
import android.widget.Button;
2016-02-25 22:02:42 +01:00
import android.widget.EditText;
import android.widget.TextView;
2016-02-25 23:19:43 +01:00
import org.json.JSONArray;
import org.json.JSONObject;
2016-02-27 15:02:28 +01:00
import org.schabi.newpipe.extractor.Parser;
2016-02-25 22:02:42 +01:00
import java.io.PrintWriter;
import java.io.StringWriter;
2016-02-27 15:02:28 +01:00
import java.text.SimpleDateFormat;
import java.util.Date;
2016-02-25 22:02:42 +01:00
import java.util.List;
2016-02-27 15:02:28 +01:00
import java.util.TimeZone;
2016-02-25 22:02:42 +01:00
import java.util.Vector;
2016-02-25 23:19:43 +01:00
/**
* Created by Christian Schabesberger on 24.10.15.
2016-02-27 15:02:28 +01:00
* <p>
2016-02-25 23:19:43 +01:00
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* ErrorActivity.java is part of NewPipe.
2016-02-27 15:02:28 +01:00
* <p>
2016-02-25 23:19:43 +01:00
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
2016-02-27 15:02:28 +01:00
* <p>
2016-02-25 23:19:43 +01:00
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
2016-02-27 15:02:28 +01:00
* <p>
2016-02-25 23:19:43 +01:00
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
2016-02-25 22:02:42 +01:00
public class ErrorActivity extends AppCompatActivity {
public static class ErrorInfo {
public int userAction;
public String request;
public String serviceName;
public int message;
public static ErrorInfo make(int userAction, String serviceName, String request, int message) {
ErrorInfo info = new ErrorInfo();
info.userAction = userAction;
info.serviceName = serviceName;
info.request = request;
info.message = message;
return info;
}
}
public static final String TAG = ErrorActivity.class.toString();
public static final int SEARCHED = 0;
public static final int REQUESTED_STREAM = 1;
2016-03-01 18:43:36 +01:00
public static final int GET_SUGGESTIONS = 2;
public static final int SOMETHING_ELSE = 3;
2016-03-11 14:56:41 +01:00
public static final int USER_REPORT = 4;
2016-08-01 01:56:19 +02:00
public static final int LOAD_IMAGE = 5;
2016-03-01 18:43:36 +01:00
public static final String SEARCHED_STRING = "searched";
public static final String REQUESTED_STREAM_STRING = "requested stream";
public static final String GET_SUGGESTIONS_STRING = "get suggestions";
public static final String SOMETHING_ELSE_STRING = "something";
2016-03-11 14:56:41 +01:00
public static final String USER_REPORT_STRING = "user report";
2016-08-01 01:56:19 +02:00
public static final String LOAD_IMAGE_STRING = "load image";
2016-03-01 18:43:36 +01:00
2016-02-27 15:57:37 +01:00
public static final String ERROR_EMAIL_ADDRESS = "crashreport@newpipe.schabi.org";
2016-02-27 15:02:28 +01:00
public static final String ERROR_EMAIL_SUBJECT = "Exception in NewPipe " + BuildConfig.VERSION_NAME;
2016-02-25 22:02:42 +01:00
2016-08-01 01:56:19 +02:00
private List<Throwable> errorList;
2016-02-25 22:02:42 +01:00
private ErrorInfo errorInfo;
private Class returnActivity;
2016-02-27 15:02:28 +01:00
private String currentTimeStamp;
private String globIpRange;
Thread globIpRangeThread;
2016-02-25 22:02:42 +01:00
// views
private TextView errorView;
2016-02-25 23:19:43 +01:00
private EditText userCommentBox;
2016-02-27 15:02:28 +01:00
private Button reportButton;
private TextView infoView;
private TextView errorMessageView;
2016-02-25 22:02:42 +01:00
2016-08-01 01:56:19 +02:00
public static void reportError(final Context context, final List<Throwable> el,
2016-02-25 22:02:42 +01:00
final Class returnAcitivty, View rootView, final ErrorInfo errorInfo) {
2016-02-27 17:02:38 +01:00
2016-02-27 15:02:28 +01:00
if (rootView != null) {
2016-02-25 22:02:42 +01:00
Snackbar.make(rootView, R.string.error_snackbar_message, Snackbar.LENGTH_LONG)
2016-02-29 21:21:15 +01:00
.setActionTextColor(Color.YELLOW)
2016-02-25 22:02:42 +01:00
.setAction(R.string.error_snackbar_action, new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityCommunicator ac = ActivityCommunicator.getCommunicator();
ac.errorList = el;
ac.returnActivity = returnAcitivty;
ac.errorInfo = errorInfo;
Intent intent = new Intent(context, ErrorActivity.class);
context.startActivity(intent);
}
}).show();
} else {
ActivityCommunicator ac = ActivityCommunicator.getCommunicator();
ac.errorList = el;
ac.returnActivity = returnAcitivty;
2016-02-29 20:33:28 +01:00
ac.errorInfo = errorInfo;
2016-02-25 22:02:42 +01:00
Intent intent = new Intent(context, ErrorActivity.class);
context.startActivity(intent);
}
}
2016-08-01 01:56:19 +02:00
public static void reportError(final Context context, final Throwable e,
2016-02-25 22:02:42 +01:00
final Class returnAcitivty, View rootView, final ErrorInfo errorInfo) {
2016-08-01 01:56:19 +02:00
List<Throwable> el = null;
2016-03-11 14:56:41 +01:00
if(e != null) {
el = new Vector<>();
el.add(e);
}
2016-02-25 22:02:42 +01:00
reportError(context, el, returnAcitivty, rootView, errorInfo);
}
// async call
2016-08-01 01:56:19 +02:00
public static void reportError(Handler handler, final Context context, final Throwable e,
2016-02-25 22:02:42 +01:00
final Class returnAcitivty, final View rootView, final ErrorInfo errorInfo) {
2016-03-11 14:56:41 +01:00
2016-08-01 01:56:19 +02:00
List<Throwable> el = null;
2016-03-11 14:56:41 +01:00
if(e != null) {
el = new Vector<>();
el.add(e);
}
2016-02-25 22:02:42 +01:00
reportError(handler, context, el, returnAcitivty, rootView, errorInfo);
}
// async call
2016-08-01 01:56:19 +02:00
public static void reportError(Handler handler, final Context context, final List<Throwable> el,
2016-02-25 22:02:42 +01:00
final Class returnAcitivty, final View rootView, final ErrorInfo errorInfo) {
handler.post(new Runnable() {
@Override
public void run() {
reportError(context, el, returnAcitivty, rootView, errorInfo);
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_error);
2016-05-25 23:51:22 +02:00
try {
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(R.string.error_report_title);
actionBar.setDisplayShowTitleEnabled(true);
2016-08-01 01:56:19 +02:00
} catch (Throwable e) {
2016-05-25 23:51:22 +02:00
Log.e(TAG, "Error turing exception handling");
e.printStackTrace();
}
2016-02-25 22:02:42 +01:00
ActivityCommunicator ac = ActivityCommunicator.getCommunicator();
errorList = ac.errorList;
returnActivity = ac.returnActivity;
errorInfo = ac.errorInfo;
2016-02-27 15:02:28 +01:00
reportButton = (Button) findViewById(R.id.errorReportButton);
2016-02-25 23:19:43 +01:00
userCommentBox = (EditText) findViewById(R.id.errorCommentBox);
2016-02-25 22:02:42 +01:00
errorView = (TextView) findViewById(R.id.errorView);
2016-02-27 15:02:28 +01:00
infoView = (TextView) findViewById(R.id.errorInfosView);
errorMessageView = (TextView) findViewById(R.id.errorMessageView);
2016-02-25 22:02:42 +01:00
errorView.setText(formErrorText(errorList));
//importand add gurumeditaion
addGuruMeditaion();
2016-02-27 15:02:28 +01:00
currentTimeStamp = getCurrentTimeStamp();
2016-02-25 22:02:42 +01:00
buildInfo(errorInfo);
2016-02-25 23:19:43 +01:00
reportButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:" + ERROR_EMAIL_ADDRESS))
.putExtra(Intent.EXTRA_SUBJECT, ERROR_EMAIL_SUBJECT)
.putExtra(Intent.EXTRA_TEXT, buildJson());
startActivity(Intent.createChooser(intent, "Send Email"));
}
});
2016-02-27 15:02:28 +01:00
reportButton.setEnabled(false);
globIpRangeThread = new Thread(new IpRagneRequester());
globIpRangeThread.start();
2016-02-27 17:02:38 +01:00
2016-02-29 21:13:02 +01:00
if(errorInfo.message != 0) {
errorMessageView.setText(errorInfo.message);
} else {
errorMessageView.setVisibility(View.GONE);
findViewById(R.id.messageWhatHappenedView).setVisibility(View.GONE);
}
2016-02-25 23:19:43 +01:00
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.error_menu, menu);
return true;
2016-02-25 22:02:42 +01:00
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
2016-02-27 15:02:28 +01:00
switch (id) {
2016-02-25 23:19:43 +01:00
case android.R.id.home:
goToReturnActivity();
break;
case R.id.menu_item_share_error: {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, buildJson());
intent.setType("text/plain");
startActivity(Intent.createChooser(intent, getString(R.string.share_dialog_title)));
}
2016-02-27 15:02:28 +01:00
break;
2016-02-25 22:02:42 +01:00
}
return false;
}
private static String getStackTrace(final Throwable throwable) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw, true);
throwable.printStackTrace(pw);
return sw.getBuffer().toString();
}
2016-08-01 01:56:19 +02:00
private String formErrorText(List<Throwable> el) {
2016-02-25 22:02:42 +01:00
String text = "";
2016-03-11 14:56:41 +01:00
if(el != null) {
2016-08-01 01:56:19 +02:00
for (Throwable e : el) {
2016-03-11 14:56:41 +01:00
text += "-------------------------------------\n"
+ getStackTrace(e);
2016-03-11 14:56:41 +01:00
}
2016-02-25 22:02:42 +01:00
}
text += "-------------------------------------";
return text;
}
private void goToReturnActivity() {
2016-02-27 15:02:28 +01:00
if (returnActivity == null) {
2016-02-25 22:02:42 +01:00
super.onBackPressed();
} else {
Intent intent;
if (returnActivity != null &&
returnActivity.isAssignableFrom(Activity.class)) {
intent = new Intent(this, returnActivity);
} else {
2016-08-02 20:59:53 +02:00
intent = new Intent(this, MainActivity.class);
2016-02-25 22:02:42 +01:00
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NavUtils.navigateUpTo(this, intent);
}
}
private void buildInfo(ErrorInfo info) {
TextView infoLabelView = (TextView) findViewById(R.id.errorInfoLabelsView);
TextView infoView = (TextView) findViewById(R.id.errorInfosView);
String text = "";
infoLabelView.setText(getString(R.string.info_labels).replace("\\n", "\n"));
2016-02-25 23:19:43 +01:00
text += getUserActionString(info.userAction)
2016-02-25 22:02:42 +01:00
+ "\n" + info.request
2016-02-25 23:19:43 +01:00
+ "\n" + getContentLangString()
2016-02-25 22:02:42 +01:00
+ "\n" + info.serviceName
2016-02-27 15:02:28 +01:00
+ "\n" + currentTimeStamp
2016-02-25 22:02:42 +01:00
+ "\n" + BuildConfig.VERSION_NAME
2016-02-25 23:19:43 +01:00
+ "\n" + getOsString();
2016-02-25 22:02:42 +01:00
infoView.setText(text);
}
2016-02-25 23:19:43 +01:00
private String buildJson() {
JSONObject errorObject = new JSONObject();
try {
errorObject.put("user_action", getUserActionString(errorInfo.userAction))
.put("request", errorInfo.request)
.put("content_language", getContentLangString())
.put("service", errorInfo.serviceName)
.put("version", BuildConfig.VERSION_NAME)
2016-02-27 15:02:28 +01:00
.put("os", getOsString())
.put("time", currentTimeStamp)
.put("ip_range", globIpRange);
2016-02-25 23:19:43 +01:00
JSONArray exceptionArray = new JSONArray();
2016-03-11 14:56:41 +01:00
if(errorList != null) {
2016-08-01 01:56:19 +02:00
for (Throwable e : errorList) {
exceptionArray.put(getStackTrace(e));
2016-03-11 14:56:41 +01:00
}
2016-02-25 23:19:43 +01:00
}
errorObject.put("exceptions", exceptionArray);
errorObject.put("user_comment", userCommentBox.getText().toString());
return errorObject.toString(3);
2016-08-01 01:56:19 +02:00
} catch (Throwable e) {
2016-02-25 23:19:43 +01:00
Log.e(TAG, "Error while erroring: Could not build json");
e.printStackTrace();
}
return "";
}
private String getUserActionString(int userAction) {
switch (userAction) {
2016-02-27 15:02:28 +01:00
case REQUESTED_STREAM:
return REQUESTED_STREAM_STRING;
case SEARCHED:
return SEARCHED_STRING;
2016-03-01 18:43:36 +01:00
case GET_SUGGESTIONS:
return GET_SUGGESTIONS_STRING;
case SOMETHING_ELSE:
return SOMETHING_ELSE_STRING;
2016-03-11 14:56:41 +01:00
case USER_REPORT:
return USER_REPORT_STRING;
case LOAD_IMAGE:
return LOAD_IMAGE_STRING;
2016-02-27 15:02:28 +01:00
default:
return "Your description is in another castle.";
2016-02-25 23:19:43 +01:00
}
}
private String getContentLangString() {
return PreferenceManager.getDefaultSharedPreferences(this)
.getString(this.getString(R.string.search_language_key), "none");
}
private String getOsString() {
String osBase = Build.VERSION.SDK_INT >= 23 ? Build.VERSION.BASE_OS : "Android";
2016-02-27 15:02:28 +01:00
return System.getProperty("os.name")
2016-02-25 23:19:43 +01:00
+ " " + (osBase.isEmpty() ? "Android" : osBase)
+ " " + Build.VERSION.RELEASE
+ " - " + Integer.toString(Build.VERSION.SDK_INT);
}
2016-02-25 22:02:42 +01:00
private void addGuruMeditaion() {
//just an easter egg
TextView sorryView = (TextView) findViewById(R.id.errorSorryView);
String text = sorryView.getText().toString();
text += "\n" + getString(R.string.guru_meditation);
sorryView.setText(text);
}
@Override
public void onBackPressed() {
//super.onBackPressed();
goToReturnActivity();
}
2016-02-27 15:02:28 +01:00
public String getCurrentTimeStamp() {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
df.setTimeZone(TimeZone.getTimeZone("GMT"));
return df.format(new Date());
}
private class IpRagneRequester implements Runnable {
Handler h = new Handler();
public void run() {
String ipRange = "none";
try {
Downloader dl = new Downloader();
String ip = dl.download("https://ifcfg.me/ip");
ipRange = Parser.matchGroup1("([0-9]*\\.[0-9]*\\.)[0-9]*\\.[0-9]*", ip)
+ "0.0";
2016-08-01 01:56:19 +02:00
} catch(Throwable e) {
2016-02-27 15:02:28 +01:00
Log.d(TAG, "Error while error: could not get iprange");
e.printStackTrace();
} finally {
h.post(new IpRageReturnRunnable(ipRange));
}
}
}
private class IpRageReturnRunnable implements Runnable {
String ipRange;
public IpRageReturnRunnable(String ipRange) {
this.ipRange = ipRange;
}
public void run() {
globIpRange = ipRange;
if(infoView != null) {
String text = infoView.getText().toString();
text += "\n" + globIpRange;
infoView.setText(text);
reportButton.setEnabled(true);
}
}
}
2016-02-25 22:02:42 +01:00
}