Переглянути джерело

Merge pull request #4056 from nextcloud/exceptionHandler

Re-enable exception handler
Andy Scherzinger 5 роки тому
батько
коміт
6773e1a510

+ 1 - 1
scripts/analysis/findbugs-results.txt

@@ -1 +1 @@
-423
+412

+ 6 - 1
src/main/AndroidManifest.xml

@@ -320,7 +320,12 @@
 
         <activity android:name=".ui.activity.LogHistoryActivity"/>
 
-        <activity android:name=".ui.errorhandling.ErrorShowActivity" />
+        <activity android:name="com.nextcloud.client.errorhandling.ShowErrorActivity"
+            android:theme="@style/Theme.ownCloud.Toolbar"
+            android:process=":crash"
+            android:excludeFromRecents="true"
+            android:finishOnTaskLaunch="true"
+            android:launchMode="singleInstance" />
         <activity android:name=".ui.activity.UploadListActivity" />
         <activity
             android:name=".ui.trashbin.TrashbinActivity"

+ 3 - 3
src/main/java/com/nextcloud/client/di/ComponentsModule.java

@@ -20,8 +20,9 @@
 
 package com.nextcloud.client.di;
 
-import com.nextcloud.client.onboarding.FirstRunActivity;
+import com.nextcloud.client.errorhandling.ShowErrorActivity;
 import com.nextcloud.client.etm.EtmActivity;
+import com.nextcloud.client.onboarding.FirstRunActivity;
 import com.nextcloud.client.onboarding.WhatsNewActivity;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.authentication.DeepLinkLoginActivity;
@@ -62,7 +63,6 @@ import com.owncloud.android.ui.activity.UploadListActivity;
 import com.owncloud.android.ui.activity.UploadPathActivity;
 import com.owncloud.android.ui.activity.UserInfoActivity;
 import com.owncloud.android.ui.dialog.ChooseTemplateDialogFragment;
-import com.owncloud.android.ui.errorhandling.ErrorShowActivity;
 import com.owncloud.android.ui.fragment.ExtendedListFragment;
 import com.owncloud.android.ui.fragment.FileDetailActivitiesFragment;
 import com.owncloud.android.ui.fragment.FileDetailFragment;
@@ -94,7 +94,7 @@ abstract class ComponentsModule {
     @ContributesAndroidInjector abstract CopyToClipboardActivity copyToClipboardActivity();
     @ContributesAndroidInjector abstract DeepLinkLoginActivity deepLinkLoginActivity();
     @ContributesAndroidInjector abstract DrawerActivity drawerActivity();
-    @ContributesAndroidInjector abstract ErrorShowActivity errorShowActivity();
+    @ContributesAndroidInjector abstract ShowErrorActivity errorShowActivity();
     @ContributesAndroidInjector abstract ErrorsWhileCopyingHandlerActivity errorsWhileCopyingHandlerActivity();
     @ContributesAndroidInjector abstract ExternalSiteWebView externalSiteWebView();
     @ContributesAndroidInjector abstract FileDisplayActivity fileDisplayActivity();

+ 117 - 0
src/main/java/com/nextcloud/client/errorhandling/ExceptionHandler.kt

@@ -0,0 +1,117 @@
+/*
+ *   Nextcloud Android client application
+ *
+ *   @author LukeOwncloud
+ *   @author AndyScherzinger
+ *   @author Tobias Kaminsky
+ *   @author Chris Narkiewicz
+ *
+ *   Copyright (C) 2016 ownCloud Inc.
+ *   Copyright (C) 2016 LukeOwncloud
+ *   Copyright (C) 2019 Andy Scherzinger
+ *   Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program 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.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.nextcloud.client.errorhandling
+
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import com.owncloud.android.BuildConfig
+import com.owncloud.android.R
+import java.io.PrintWriter
+import java.io.StringWriter
+
+class ExceptionHandler(
+    private val context: Context,
+    private val defaultExceptionHandler: Thread.UncaughtExceptionHandler
+) : Thread.UncaughtExceptionHandler {
+
+    companion object {
+        private const val LINE_SEPARATOR = "\n"
+    }
+
+    override fun uncaughtException(thread: Thread, exception: Throwable) {
+
+        @Suppress("TooGenericExceptionCaught") // this is exactly what we want here
+        try {
+            val stackTrace = StringWriter()
+            exception.printStackTrace(PrintWriter(stackTrace))
+            val errorReport = generateErrorReport(stackTrace.toString())
+            val intent = Intent(context, ShowErrorActivity::class.java)
+            intent.putExtra(ShowErrorActivity.EXTRA_ERROR_TEXT, errorReport)
+            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+            context.startActivity(intent)
+            // Pass exception to OS for graceful handling - OS will report it via ADB
+            // and close all activities and services.
+            defaultExceptionHandler.uncaughtException(thread, exception)
+        } catch (fatalException: Exception) {
+            // do not recurse into custom handler if exception is thrown during
+            // exception handling. Pass this ultimate fatal exception to OS
+            defaultExceptionHandler.uncaughtException(thread, fatalException)
+        }
+    }
+
+    private fun generateErrorReport(stackTrace: String): String {
+        val buildNumber = context.resources.getString(R.string.buildNumber)
+
+        var buildNumberString = ""
+        if (buildNumber.isNotEmpty()) {
+            buildNumberString = " (build #$buildNumber)"
+        }
+
+        return "************ CAUSE OF ERROR ************\n\n" +
+            stackTrace +
+            "\n************ APP INFORMATION ************" +
+            LINE_SEPARATOR +
+            "ID: " +
+            BuildConfig.APPLICATION_ID +
+            LINE_SEPARATOR +
+            "Version: " +
+            BuildConfig.VERSION_CODE +
+            buildNumberString +
+            LINE_SEPARATOR +
+            "Build flavor: " +
+            BuildConfig.FLAVOR +
+            LINE_SEPARATOR +
+            "\n************ DEVICE INFORMATION ************" +
+            LINE_SEPARATOR +
+            "Brand: " +
+            Build.BRAND +
+            LINE_SEPARATOR +
+            "Device: " +
+            Build.DEVICE +
+            LINE_SEPARATOR +
+            "Model: " +
+            Build.MODEL +
+            LINE_SEPARATOR +
+            "Id: " +
+            Build.ID +
+            LINE_SEPARATOR +
+            "Product: " +
+            Build.PRODUCT +
+            LINE_SEPARATOR +
+            "\n************ FIRMWARE ************" +
+            LINE_SEPARATOR +
+            "SDK: " +
+            Build.VERSION.SDK_INT +
+            LINE_SEPARATOR +
+            "Release: " +
+            Build.VERSION.RELEASE +
+            LINE_SEPARATOR +
+            "Incremental: " +
+            Build.VERSION.INCREMENTAL +
+            LINE_SEPARATOR
+    }
+}

+ 90 - 0
src/main/java/com/nextcloud/client/errorhandling/ShowErrorActivity.kt

@@ -0,0 +1,90 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2019 Andy Scherzinger <info@andy-scherzinger.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.nextcloud.client.errorhandling
+
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.view.Menu
+import android.view.MenuItem
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import com.google.android.material.snackbar.Snackbar
+import com.owncloud.android.R
+import com.owncloud.android.utils.ClipboardUtil
+import com.owncloud.android.utils.DisplayUtils
+import kotlinx.android.synthetic.main.activity_show_error.*
+import kotlinx.android.synthetic.main.toolbar_standard.*
+
+class ShowErrorActivity : AppCompatActivity() {
+    companion object {
+        const val EXTRA_ERROR_TEXT = "error"
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_show_error)
+
+        text_view_error.text = intent.getStringExtra(EXTRA_ERROR_TEXT)
+
+        setSupportActionBar(toolbar)
+        supportActionBar!!.title = createErrorTitle()
+
+        val snackbar = DisplayUtils.createSnackbar(
+            error_page_container,
+            R.string.error_report_issue_text, Snackbar.LENGTH_INDEFINITE)
+            .setAction(R.string.error_report_issue_action) { reportIssue() }
+
+        snackbar.show()
+    }
+
+    private fun createErrorTitle() = String.format(getString(R.string.error_crash_title), getString(R.string.app_name))
+
+    private fun reportIssue() {
+        ClipboardUtil.copyToClipboard(this, text_view_error.text.toString(), false)
+        val issueLink = getString(R.string.report_issue_link)
+        if (issueLink.isNotEmpty()) {
+            val uriUrl = Uri.parse(issueLink)
+            val intent = Intent(Intent.ACTION_VIEW, uriUrl)
+            DisplayUtils.startIntentIfAppAvailable(intent, this, R.string.no_browser_available)
+        }
+        Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_LONG).show()
+    }
+
+    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
+        menuInflater.inflate(R.menu.activity_error_show, menu)
+        return super.onCreateOptionsMenu(menu)
+    }
+
+    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
+        return when (item?.itemId) {
+            R.id.error_share -> { onClickedShare(); true }
+            else -> super.onOptionsItemSelected(item)
+        }
+    }
+
+    private fun onClickedShare() {
+        val intent = Intent(Intent.ACTION_SEND)
+        intent.putExtra(Intent.EXTRA_SUBJECT, createErrorTitle())
+        intent.putExtra(Intent.EXTRA_TEXT, text_view_error.text)
+        intent.type = "text/plain"
+        startActivity(intent)
+    }
+}

+ 34 - 6
src/main/java/com/owncloud/android/MainApp.java

@@ -25,6 +25,8 @@ import android.Manifest;
 import android.accounts.Account;
 import android.annotation.SuppressLint;
 import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Application;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.content.ContentResolver;
@@ -42,11 +44,10 @@ import android.view.WindowManager;
 import com.evernote.android.job.JobManager;
 import com.evernote.android.job.JobRequest;
 import com.nextcloud.client.account.UserAccountManager;
-import com.nextcloud.client.appinfo.AppInfo;
 import com.nextcloud.client.device.PowerManagementService;
 import com.nextcloud.client.di.ActivityInjector;
-import com.nextcloud.client.di.AppComponent;
 import com.nextcloud.client.di.DaggerAppComponent;
+import com.nextcloud.client.errorhandling.ExceptionHandler;
 import com.nextcloud.client.network.ConnectivityService;
 import com.nextcloud.client.onboarding.OnboardingService;
 import com.nextcloud.client.preferences.AppPreferences;
@@ -128,9 +129,6 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
     @Inject
     protected UploadsStorageManager uploadsStorageManager;
 
-    @Inject
-    protected AppInfo appInfo;
-
     @Inject
     protected OnboardingService onboarding;
 
@@ -167,9 +165,40 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
         return powerManagementService;
     }
 
+    private String getAppProcessName() {
+        String processName = "";
+        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
+            ActivityManager manager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
+            final int ownPid = android.os.Process.myPid();
+            final List<ActivityManager.RunningAppProcessInfo> processes = manager.getRunningAppProcesses();
+            if (processes != null) {
+                for (ActivityManager.RunningAppProcessInfo info : processes) {
+                    if (info.pid == ownPid) {
+                        processName = info.processName;
+                        break;
+                    }
+                }
+            }
+        } else {
+            processName = Application.getProcessName();
+        }
+        return processName;
+    }
+
     @Override
     protected void attachBaseContext(Context base) {
         super.attachBaseContext(base);
+
+        // we don't want to handle crashes occuring inside crash reporter activity/process;
+        // let the platform deal with those
+        final boolean isCrashReportingProcess = getAppProcessName().endsWith(":crash");
+        if (!isCrashReportingProcess) {
+            Thread.UncaughtExceptionHandler defaultPlatformHandler = Thread.getDefaultUncaughtExceptionHandler();
+            final ExceptionHandler crashReporter = new ExceptionHandler(this,
+                                                                        defaultPlatformHandler);
+            Thread.setDefaultUncaughtExceptionHandler(crashReporter);
+        }
+
         initGlobalContext(this);
         DaggerAppComponent.builder()
             .application(this)
@@ -181,7 +210,6 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
     @Override
     public void onCreate() {
         super.onCreate();
-
         registerActivityLifecycleCallbacks(new ActivityInjector());
 
         Thread t = new Thread(() -> {

+ 0 - 1
src/main/java/com/owncloud/android/operations/CreateShareWithShareeOperation.java

@@ -21,7 +21,6 @@
 
 package com.owncloud.android.operations;
 
-import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;

+ 0 - 1
src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java

@@ -134,7 +134,6 @@ public class ActivitiesActivity extends FileActivity implements ActivityListInte
         emptyContentProgressBar.setVisibility(View.GONE);
         emptyContentMessage.setVisibility(View.INVISIBLE);
         emptyContentHeadline.setVisibility(View.INVISIBLE);
-
     }
 
     protected void onCreateSwipeToRefresh(SwipeRefreshLayout refreshLayout) {

+ 0 - 1
src/main/java/com/owncloud/android/ui/activity/SettingsActivity.java

@@ -136,7 +136,6 @@ public class SettingsActivity extends PreferenceActivity
     @SuppressWarnings("deprecation")
     @Override
     public void onCreate(Bundle savedInstanceState) {
-
         if (ThemeUtils.themingEnabled(this)) {
             setTheme(R.style.FallbackThemingTheme);
         }

+ 0 - 45
src/main/java/com/owncloud/android/ui/errorhandling/ErrorShowActivity.java

@@ -1,45 +0,0 @@
-/**
- *   ownCloud Android client application
- *
- *   @author LukeOwncloud
- *   Copyright (C) 2016 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program 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.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-package com.owncloud.android.ui.errorhandling;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.Log;
-import android.widget.TextView;
-
-import com.owncloud.android.R;
-
-public class ErrorShowActivity extends Activity {
-
-	private static final String TAG = ErrorShowActivity.class.getSimpleName();
-
-	TextView mError;
-
-	@Override
-	protected void onCreate(Bundle savedInstanceState) {
-		super.onCreate(savedInstanceState);
-		Log.e(TAG, "ErrorShowActivity was called. See above for StackTrace.");
-		Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
-		setContentView(R.layout.errorhandling_showerror);
-		mError = (TextView) findViewById(R.id.errorTextView);
-		mError.setText(getIntent().getStringExtra("error"));
-
-	}
-}

+ 0 - 82
src/main/java/com/owncloud/android/ui/errorhandling/ExceptionHandler.java

@@ -1,82 +0,0 @@
-/**
- *   ownCloud Android client application
- *
- *   @author LukeOwncloud
- *   Copyright (C) 2016 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program 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.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-package com.owncloud.android.ui.errorhandling;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Build;
-import android.util.Log;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
-	private final Activity mContext;
-
-	private static final String TAG = ExceptionHandler.class.getSimpleName();
-
-	public ExceptionHandler(Activity context) {
-		mContext = context;
-	}
-
-	public void uncaughtException(Thread thread, Throwable exception) {
-	    Log.e(TAG, "ExceptionHandler caught UncaughtException", exception);
-		StringWriter stackTrace = new StringWriter();
-		exception.printStackTrace(new PrintWriter(stackTrace));
-		final StringBuilder errorReport = new StringBuilder(192);
-		final String LINE_SEPARATOR = "\n";
-		errorReport.append("************ CAUSE OF ERROR ************\n\n")
-				.append(stackTrace.toString())
-				.append("\n************ DEVICE INFORMATION ***********\nBrand: ")
-				.append(Build.BRAND)
-				.append(LINE_SEPARATOR)
-				.append("Device: ")
-				.append(Build.DEVICE)
-				.append(LINE_SEPARATOR)
-				.append("Model: ")
-				.append(Build.MODEL)
-				.append(LINE_SEPARATOR)
-				.append("Id: ")
-				.append(Build.ID)
-				.append(LINE_SEPARATOR)
-				.append("Product: ")
-				.append(Build.PRODUCT)
-				.append(LINE_SEPARATOR)
-				.append("\n************ FIRMWARE ************\nSDK: ")
-				.append(Build.VERSION.SDK_INT)
-				.append(LINE_SEPARATOR)
-				.append("Release: ")
-				.append(Build.VERSION.RELEASE)
-				.append(LINE_SEPARATOR)
-				.append("Incremental: ")
-				.append(Build.VERSION.INCREMENTAL)
-				.append(LINE_SEPARATOR);
-
-		Log.e(TAG, "An exception was thrown and handled by ExceptionHandler:", exception);
-
-		Intent intent = new Intent(mContext, ErrorShowActivity.class);
-		intent.putExtra("error", errorReport.toString());
-		mContext.startActivity(intent);
-
-		android.os.Process.killProcess(android.os.Process.myPid());
-		System.exit(1000);
-	}
-
-}

+ 45 - 0
src/main/res/layout/activity_show_error.xml

@@ -0,0 +1,45 @@
+<!--
+  Nextcloud Android client application
+
+  Copyright (C) 2019 Andy Scherzinger
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+  License as published by the Free Software Foundation; either
+  version 3 of the License, or any later version.
+
+  This program 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+
+  You should have received a copy of the GNU Affero General Public
+  License along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".ui.errorhandling.ShowErrorActivity">
+
+    <include layout="@layout/toolbar_standard" />
+
+    <ScrollView
+        android:id="@+id/error_page_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_behavior="@string/appbar_scrolling_view_behavior">
+
+        <TextView
+            android:id="@+id/text_view_error"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingLeft="@dimen/standard_padding"
+            android:paddingRight="@dimen/standard_padding"
+            android:paddingTop="@dimen/standard_padding"
+            android:paddingBottom="@dimen/standard_list_item_size" />
+
+    </ScrollView>
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout>

+ 0 - 11
src/main/res/layout/errorhandling_showerror.xml

@@ -1,11 +0,0 @@
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent" >
-
-    <TextView
-        android:id="@+id/errorTextView"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
-</ScrollView>

+ 32 - 0
src/main/res/menu/activity_error_show.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+    Nextcloud Android client application
+
+    @author Andy Scherzinger
+    Copyright (C) 2019 Andy Scherzinger <info@andy-scherzinger.de>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program 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 Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:ignore="AppCompatResource">
+
+    <item
+        android:id="@+id/error_share"
+        android:icon="@drawable/ic_share"
+        android:showAsAction="ifRoom"
+        android:title="@string/common_share"
+        app:showAsAction="ifRoom" />
+
+</menu>

+ 1 - 1
src/main/res/menu/etm_preferences.xml

@@ -25,7 +25,7 @@
 
     <item
         android:id="@+id/etm_preferences_share"
-        android:title="@string/etm_share"
+        android:title="@string/common_share"
         app:showAsAction="ifRoom"
         android:showAsAction="ifRoom"
         android:icon="@drawable/ic_share" />

+ 1 - 1
src/main/res/values/setup.xml

@@ -123,7 +123,7 @@
     <string name="help_link" translatable="false">https://help.nextcloud.com/c/clients/android</string>
     <string name="translation_link" translatable="false">https://www.transifex.com/nextcloud/nextcloud/android/</string>
     <string name="contributing_link" translatable="false">https://github.com/nextcloud/android/blob/master/CONTRIBUTING.md</string>
-    <string name="report_issue_link" translatable="false">https://github.com/nextcloud/android/issues</string>
+    <string name="report_issue_link" translatable="false">https://github.com/nextcloud/android/issues/new/choose</string>
 
     <!-- login data links -->
     <string name="login_data_own_scheme" translatable="false">nc</string>

+ 6 - 1
src/main/res/values/strings.xml

@@ -136,6 +136,7 @@
     <string name="common_pending">Pending</string>
     <string name="common_delete">Delete</string>
     <string name="common_send">Send</string>
+    <string name="common_share">Share</string>
     <string name="about_title">About</string>
     <string name="delete_account">Remove account</string>
     <string name="delete_account_warning">Remove account %s and delete all local files?\n\nDeletion cannot be undone.</string>
@@ -886,5 +887,9 @@
 
     <string name="etm_title">Engineering Test Mode</string>
     <string name="etm_preferences">Preferences</string>
-    <string name="etm_share">Share</string>
+
+    <string name="error_report_issue_text">Report issue to tracker? (requires a Github account)</string>
+    <string name="error_report_issue_action">Report</string>
+    <string name="error_crash_title">%1$s crashed</string>
+    <string name="copied_to_clipboard">Copied to clipboard</string>
 </resources>