Browse Source

Merge pull request #3187 from nextcloud/handleNoApps

Wrapper to start urls/intents if no app is available
Andy Scherzinger 6 years ago
parent
commit
831f083153

+ 16 - 15
src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java

@@ -203,7 +203,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
     private AccountManager mAccountMgr;
     private Uri mNewCapturedUriFromOAuth2Redirection;
 
-    /// Server PRE-Fragment elements 
+    /// Server PRE-Fragment elements
     private CustomEditText mHostUrlInput;
     private View mRefreshButton;
     private TextView mServerStatusView;
@@ -217,7 +217,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
 
     private GetServerInfoOperation.ServerInfo mServerInfo = new GetServerInfoOperation.ServerInfo();
 
-    /// Authentication PRE-Fragment elements 
+    /// Authentication PRE-Fragment elements
     private CheckBox mOAuth2Check;
     private TextView mOAuthAuthEndpointText;
     private TextView mOAuthTokenEndpointText;
@@ -237,7 +237,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
 
     private boolean mIsFirstAuthAttempt;
 
-    /// Identifier of operation in progress which result shouldn't be lost 
+    /// Identifier of operation in progress which result shouldn't be lost
     private long mWaitingForOpId = Long.MAX_VALUE;
 
     private String basicTokenType;
@@ -264,7 +264,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         if (savedInstanceState == null) {
             FirstRunActivity.runIfNeeded(this);
         }
-        
+
         basicTokenType = AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType(this));
         oauthTokenType = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType(this));
         samlTokenType = AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType(this));
@@ -379,7 +379,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         mLoginWebView.getSettings().setAllowFileAccess(false);
         mLoginWebView.getSettings().setJavaScriptEnabled(true);
         mLoginWebView.getSettings().setDomStorageEnabled(true);
-        
+
         if (useGenericUserAgent) {
             mLoginWebView.getSettings().setUserAgentString(MainApp.getNextcloudUserAgent());
         } else {
@@ -1339,7 +1339,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         uri = uriBuilder.build();
         Log_OC.d(TAG, "Starting browser to view " + uri.toString());
         Intent i = new Intent(Intent.ACTION_VIEW, uri);
-        startActivity(i);
+
+        DisplayUtils.startIntentIfAppAvailable(i, this, R.string.no_browser_available);
     }
 
 
@@ -1371,7 +1372,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         if (operation instanceof GetServerInfoOperation) {
             if (operation.hashCode() == mWaitingForOpId) {
                 onGetServerInfoFinish(result);
-            }   // else nothing ; only the last check operation is considered; 
+            }   // else nothing ; only the last check operation is considered;
             // multiple can be started if the user amends a URL quickly
 
         } else if (operation instanceof OAuth2GetAccessToken) {
@@ -1456,7 +1457,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             //      1. connection succeeded, and we know if it's SSL or not
             //      2. server is installed
             //      3. we got the server version
-            //      4. we got the authentication method required by the server 
+            //      4. we got the authentication method required by the server
             mServerInfo = (GetServerInfoOperation.ServerInfo) (result.getData().get(0));
 
             // show outdated warning
@@ -1776,7 +1777,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             }
 
         } else if (result.isServerFail() || result.isException()) {
-            /// server errors or exceptions in authorization take to requiring a new check of 
+            /// server errors or exceptions in authorization take to requiring a new check of
             /// the server
             mServerIsChecked = true;
             mServerIsValid = false;
@@ -1837,13 +1838,13 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
 
         if (AccountTypeUtils.getAuthTokenTypeAccessToken(accountType).equals(mAuthTokenType)) {
             response.putString(AccountManager.KEY_AUTHTOKEN, mAuthToken);
-            // the next line is necessary, notifications are calling directly to the 
+            // the next line is necessary, notifications are calling directly to the
             // AuthenticatorActivity to update, without AccountManager intervention
             mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);
 
         } else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(accountType).equals(mAuthTokenType)) {
             response.putString(AccountManager.KEY_AUTHTOKEN, mAuthToken);
-            // the next line is necessary; by now, notifications are calling directly to the 
+            // the next line is necessary; by now, notifications are calling directly to the
             // AuthenticatorActivity to update, without AccountManager intervention
             mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);
 
@@ -1938,7 +1939,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             }
 
             /// prepare result to return to the Authenticator
-            //  TODO check again what the Authenticator makes with it; probably has the same 
+            //  TODO check again what the Authenticator makes with it; probably has the same
             //  effect as addAccountExplicitly, but it's not well done
             final Intent intent = new Intent();
             intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, accountType);
@@ -1947,7 +1948,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             if (isOAuth || isSaml) {
                 mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);
             }
-            /// add user data to the new account; TODO probably can be done in the last parameter 
+            /// add user data to the new account; TODO probably can be done in the last parameter
             //      addAccountExplicitly, or in KEY_USERDATA
             mAccountMgr.setUserData(mAccount, Constants.KEY_OC_VERSION, mServerInfo.mVersion.getVersion());
             mAccountMgr.setUserData(mAccount, Constants.KEY_OC_BASE_URL, mServerInfo.mBaseUrl);
@@ -2053,7 +2054,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
 
     /**
      * Called when the 'action' button in an IME is pressed ('enter' in software keyboard).
-     * 
+     *
      * Used to trigger the authentication check when the user presses 'enter' after writing the
      * password, or to throw the server test when the only field on screen is the URL input field.
      */
@@ -2192,7 +2193,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
     public void onSavedCertificate() {
         Fragment fd = getSupportFragmentManager().findFragmentByTag(SAML_DIALOG_TAG);
         if (fd == null) {
-            // if SAML dialog is not shown, 
+            // if SAML dialog is not shown,
             // the SslDialog was shown due to an SSL error in the server check
             checkOcServer();
         }

+ 2 - 1
src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java

@@ -545,7 +545,8 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
         for (ExternalLink link : externalLinksProvider.getExternalLink(ExternalLinkType.LINK)) {
             if (menuItem.getTitle().toString().equalsIgnoreCase(link.name)) {
                 if (link.redirect) {
-                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link.url)));
+                    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link.url));
+                    DisplayUtils.startIntentIfAppAvailable(intent, this, R.string.no_browser_available);
                 } else {
                     Intent externalWebViewIntent = new Intent(getApplicationContext(), ExternalSiteWebView.class);
                     externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_TITLE, link.name);

+ 3 - 3
src/main/java/com/owncloud/android/ui/activity/FileActivity.java

@@ -613,7 +613,7 @@ public abstract class FileActivity extends DrawerActivity
         LoadingVersionNumberTask loadTask = new LoadingVersionNumberTask(callback);
         loadTask.execute(url);
     }
-    
+
     public static void showDevSnackbar(Activity activity, Integer latestVersion, boolean openDirectly) {
         Integer currentVersion = -1;
         try {
@@ -630,7 +630,7 @@ public abstract class FileActivity extends DrawerActivity
                 String devApkLink = (String) activity.getText(R.string.dev_link) + latestVersion + ".apk";
                 Uri uriUrl = Uri.parse(devApkLink);
                 Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
-                activity.startActivity(intent);
+                DisplayUtils.startIntentIfAppAvailable(intent, activity, R.string.no_browser_available);
             } else {
                 Snackbar.make(activity.findViewById(android.R.id.content), R.string.dev_version_new_version_available,
                         Snackbar.LENGTH_LONG)
@@ -638,7 +638,7 @@ public abstract class FileActivity extends DrawerActivity
                             String devApkLink = (String) activity.getText(R.string.dev_link) + latestVersion + ".apk";
                             Uri uriUrl = Uri.parse(devApkLink);
                             Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
-                            activity.startActivity(intent);
+                            DisplayUtils.startIntentIfAppAvailable(intent, activity, R.string.no_browser_available);
                         }).show();
             }
         } else {

+ 5 - 4
src/main/java/com/owncloud/android/ui/activity/FirstRunActivity.java

@@ -63,7 +63,7 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
         setContentView(R.layout.first_run_activity);
 
         boolean isProviderOrOwnInstallationVisible = getResources().getBoolean(R.bool.show_provider_or_own_installation);
-        
+
         setSlideshowSize(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
 
         Button loginButton = findViewById(R.id.login);
@@ -181,7 +181,7 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
         if (!isProviderOrOwnInstallationVisible) {
             return false;
         }
-        
+
         if (context instanceof FirstRunActivity) {
             return false;
         }
@@ -210,7 +210,8 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
     }
 
     public void onHostYourOwnServerClick(View view) {
-        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.url_server_install))));
+        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.url_server_install)));
+        DisplayUtils.startIntentIfAppAvailable(intent, this, R.string.no_browser_available);
     }
 
     @Override
@@ -224,7 +225,7 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
                 DisplayUtils.showSnackMessage(this, R.string.account_creation_failed);
                 return;
             }
-            
+
             setAccount(account);
             AccountUtils.setCurrentOwnCloudAccount(this, account.name);
             onAccountSet(false);

+ 6 - 11
src/main/java/com/owncloud/android/ui/activity/ParticipateActivity.java

@@ -23,7 +23,6 @@ package com.owncloud.android.ui.activity;
 
 import android.content.Intent;
 import android.graphics.PorterDuff;
-import android.net.Uri;
 import android.os.Bundle;
 import android.support.v7.widget.AppCompatButton;
 import android.text.Html;
@@ -33,6 +32,7 @@ import android.view.View;
 import android.widget.TextView;
 
 import com.owncloud.android.R;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.ThemeUtils;
 
 /**
@@ -94,28 +94,23 @@ public class ParticipateActivity extends FileActivity {
 
         AppCompatButton reportButton = findViewById(R.id.participate_testing_report);
         reportButton.getBackground().setColorFilter(ThemeUtils.primaryAccentColor(this), PorterDuff.Mode.SRC_ATOP);
-        reportButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.report_issue_link))));
-            }
-        });
+        reportButton.setOnClickListener(v -> DisplayUtils.startLinkIntent(this, R.string.report_issue_link));
     }
 
     public void onGetBetaFDroidClick(View view) {
-        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.fdroid_beta_link))));
+        DisplayUtils.startLinkIntent(this, R.string.fdroid_beta_link);
     }
 
     public void onGetRCFDroidClick(View view) {
-        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.fdroid_link))));
+        DisplayUtils.startLinkIntent(this, R.string.fdroid_link);
     }
 
     public void onGetRCPlayStoreClick(View view) {
-        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.play_store_register_beta))));
+        DisplayUtils.startLinkIntent(this, R.string.play_store_register_beta);
     }
 
     public void onGetBetaApkClick(View view) {
-        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.beta_apk_link))));
+        DisplayUtils.startLinkIntent(this, R.string.beta_apk_link);
     }
 
     @Override

+ 11 - 20
src/main/java/com/owncloud/android/ui/activity/Preferences.java

@@ -172,7 +172,7 @@ public class Preferences extends PreferenceActivity
 
         // About
         setupAboutCategory(accentColor, appVersion);
-        
+
         // Dev
         setupDevCategory(accentColor, preferenceScreen);
     }
@@ -202,10 +202,7 @@ public class Preferences extends PreferenceActivity
             Preference pChangelogLink = findPreference("changelog_link");
             if (pChangelogLink != null) {
                 pChangelogLink.setOnPreferenceClickListener(preference -> {
-                    String devChangelogLink = getString(R.string.dev_changelog);
-                    Uri uriUrl = Uri.parse(devChangelogLink);
-                    Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
-                    startActivity(intent);
+                    DisplayUtils.startLinkIntent(this, R.string.dev_changelog);
                     return true;
                 });
             }
@@ -230,14 +227,10 @@ public class Preferences extends PreferenceActivity
         boolean licenseEnabled = getResources().getBoolean(R.bool.license_enabled);
         Preference licensePreference = findPreference("license");
         if (licensePreference != null) {
-            String licenseUrl = getString(R.string.license_url);
-
-            if (licenseEnabled && !licenseUrl.isEmpty()) {
+            if (licenseEnabled) {
                 licensePreference.setSummary(R.string.prefs_gpl_v2);
                 licensePreference.setOnPreferenceClickListener(preference -> {
-                    Uri uriUrl = Uri.parse(licenseUrl);
-                    Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
-                    startActivity(intent);
+                    DisplayUtils.startLinkIntent(this, R.string.license_url);
                     return true;
                 });
             } else {
@@ -258,6 +251,7 @@ public class Preferences extends PreferenceActivity
                         Intent intent;
                         if ("application/pdf".equals(mimeType)) {
                             intent = new Intent(Intent.ACTION_VIEW, privacyUrl);
+                            DisplayUtils.startIntentIfAppAvailable(intent, this, R.string.no_pdf_app_available);
                         } else {
                             intent = new Intent(getApplicationContext(), ExternalSiteWebView.class);
                             intent.putExtra(ExternalSiteWebView.EXTRA_TITLE,
@@ -283,12 +277,9 @@ public class Preferences extends PreferenceActivity
         boolean sourcecodeEnabled = getResources().getBoolean(R.bool.sourcecode_enabled);
         Preference sourcecodePreference = findPreference("sourcecode");
         if (sourcecodePreference != null) {
-            String sourcecodeUrl = getString(R.string.sourcecode_url);
-            if (sourcecodeEnabled && !sourcecodeUrl.isEmpty()) {
+            if (sourcecodeEnabled) {
                 sourcecodePreference.setOnPreferenceClickListener(preference -> {
-                    Uri uriUrl = Uri.parse(sourcecodeUrl);
-                    Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
-                    startActivity(intent);
+                    DisplayUtils.startLinkIntent(this, R.string.sourcecode_url);
                     return true;
                 });
             } else {
@@ -332,7 +323,7 @@ public class Preferences extends PreferenceActivity
                     if (!imprintWeb.isEmpty()) {
                         Uri uriUrl = Uri.parse(imprintWeb);
                         Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
-                        startActivity(intent);
+                        DisplayUtils.startIntentIfAppAvailable(intent, this, R.string.no_browser_available);
                     }
                     //ImprintDialog.newInstance(true).show(preference.get, "IMPRINT_DIALOG");
                     return true;
@@ -460,7 +451,7 @@ public class Preferences extends PreferenceActivity
                     if (!helpWeb.isEmpty()) {
                         Uri uriUrl = Uri.parse(helpWeb);
                         Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
-                        startActivity(intent);
+                        DisplayUtils.startIntentIfAppAvailable(intent, this, R.string.no_browser_available);
                     }
                     return true;
                 });
@@ -803,7 +794,7 @@ public class Preferences extends PreferenceActivity
                 // no f-droid market app or Play store installed --> launch browser for f-droid url
                 Intent downloadIntent = new Intent(Intent.ACTION_VIEW,
                         Uri.parse("https://f-droid.org/repository/browse/?fdid=at.bitfire.davdroid"));
-                startActivity(downloadIntent);
+                DisplayUtils.startIntentIfAppAvailable(downloadIntent, this, R.string.no_browser_available);
 
                 DisplayUtils.showSnackMessage(this, R.string.prefs_calendar_contacts_no_store_error);
             }
@@ -891,7 +882,7 @@ public class Preferences extends PreferenceActivity
             builder.show();
         }
     }
-    
+
     @Override
     @NonNull
     public MenuInflater getMenuInflater() {

+ 3 - 1
src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java

@@ -272,7 +272,9 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
     }
 
     private void openLink(String link) {
-        notificationsActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link)));
+        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
+
+        DisplayUtils.startIntentIfAppAvailable(intent, notificationsActivity, R.string.no_browser_available);
     }
 
     @Override

+ 6 - 10
src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java

@@ -23,9 +23,7 @@ package com.owncloud.android.ui.fragment;
 import android.accounts.Account;
 import android.app.SearchManager;
 import android.content.Context;
-import android.content.Intent;
 import android.content.res.Resources;
-import android.net.Uri;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.design.widget.Snackbar;
@@ -63,6 +61,7 @@ import com.owncloud.android.ui.dialog.SharePasswordDialogFragment;
 import com.owncloud.android.ui.fragment.util.FileDetailSharingFragmentHelper;
 import com.owncloud.android.ui.fragment.util.SharingMenuHelper;
 import com.owncloud.android.utils.ClipboardUtil;
+import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.ThemeUtils;
 
 import java.util.List;
@@ -373,11 +372,8 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
     public void showNotSupportedByOcMessage() {
         if (getView() != null) {
             Snackbar.make(getView(), R.string.files_drop_not_supported, Snackbar.LENGTH_LONG)
-                    .setAction(R.string.learn_more, v -> {
-                        Intent i = new Intent(Intent.ACTION_VIEW);
-                        i.setData(Uri.parse(getString(R.string.url_server_install)));
-                        startActivity(i);
-                    })
+                .setAction(R.string.learn_more, v ->
+                    DisplayUtils.startLinkIntent(requireActivity(), R.string.url_server_install))
                     .show();
         }
     }
@@ -473,7 +469,7 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
 
     /**
      * Get known server capabilities from DB
-     * 
+     *
      * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
      * instance ready to use. If not ready, does nothing.
      */
@@ -485,9 +481,9 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
 
     /**
      * Get public link from the DB to fill in the "Share link" section in the UI.
-     * 
+     *
      * Takes into account server capabilities before reading database.
-     * 
+     *
      * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
      * instance ready to use. If not ready, does nothing.
      */

+ 3 - 11
src/main/java/com/owncloud/android/ui/fragment/ShareFileFragment.java

@@ -25,10 +25,8 @@ package com.owncloud.android.ui.fragment;
 
 import android.accounts.Account;
 import android.app.Activity;
-import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.PorterDuff;
-import android.net.Uri;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.design.widget.Snackbar;
@@ -62,8 +60,8 @@ import com.owncloud.android.utils.MimeTypeUtil;
 import com.owncloud.android.utils.ThemeUtils;
 
 import java.text.SimpleDateFormat;
-import java.util.List;
 import java.util.Date;
+import java.util.List;
 
 /**
  * Fragment for Sharing a file with sharees (users or groups) or creating
@@ -543,14 +541,8 @@ public class ShareFileFragment extends Fragment implements ShareUserListAdapter.
             } else {
                 // not supported in ownCloud
                 Snackbar.make(getView(), R.string.files_drop_not_supported, Snackbar.LENGTH_LONG)
-                        .setAction(R.string.learn_more, new View.OnClickListener(){
-                            @Override
-                            public void onClick(View v) {
-                                Intent i = new Intent(Intent.ACTION_VIEW);
-                                i.setData(Uri.parse(getString(R.string.url_server_install)));
-                                startActivity(i);
-                            }
-                        })
+                    .setAction(R.string.learn_more, v ->
+                        DisplayUtils.startLinkIntent(requireActivity(), R.string.url_server_install))
                         .show();
             }
 

+ 14 - 1
src/main/java/com/owncloud/android/utils/DisplayUtils.java

@@ -765,7 +765,7 @@ public final class DisplayUtils {
 
         return (int) (dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT));
     }
-    
+
     static public void showServerOutdatedSnackbar(Activity activity) {
         Snackbar.make(activity.findViewById(android.R.id.content),
                 R.string.outdated_server, Snackbar.LENGTH_INDEFINITE)
@@ -773,4 +773,17 @@ public final class DisplayUtils {
                 })
                 .show();
     }
+
+    static public void startLinkIntent(Activity activity, @StringRes int link) {
+        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(activity.getString(link)));
+        DisplayUtils.startIntentIfAppAvailable(intent, activity, R.string.no_browser_available);
+    }
+
+    static public void startIntentIfAppAvailable(Intent intent, Activity activity, @StringRes int error) {
+        if (intent.resolveActivity(activity.getPackageManager()) != null) {
+            activity.startActivity(intent);
+        } else {
+            DisplayUtils.showSnackMessage(activity, error);
+        }
+    }
 }

+ 9 - 9
src/main/res/layout/participate_layout.xml

@@ -95,24 +95,24 @@
                     android:layout_height="wrap_content">
 
                     <ImageButton
-                        android:id="@+id/participate_release_candidate_playstore"
+                        android:id="@+id/participate_release_candidate_fdroid"
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
                         android:background="@color/white"
-                        android:onClick="onGetRCPlayStoreClick"
+                        android:onClick="onGetRCFDroidClick"
                         android:padding="@dimen/zero"
-                        android:src="@drawable/playstore"
-                        android:contentDescription="@string/participate_rc_play_store"/>
+                        android:src="@drawable/fdroid"
+                        android:contentDescription="@string/participate_rc_fdroid"/>
 
                     <ImageButton
-                        android:id="@+id/participate_release_candidate_fdroid"
+                        android:id="@+id/participate_release_candidate_playstore"
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
                         android:background="@color/white"
-                        android:onClick="onGetRCFDroidClick"
+                        android:onClick="onGetRCPlayStoreClick"
                         android:padding="@dimen/zero"
-                        android:src="@drawable/fdroid"
-                        android:contentDescription="@string/participate_rc_fdroid"/>
+                        android:src="@drawable/playstore"
+                        android:contentDescription="@string/participate_rc_play_store"/>
 
                 </LinearLayout>
 
@@ -204,4 +204,4 @@
         android:layout_height="match_parent"
         android:layout_gravity="start"/>
 
-</android.support.v4.widget.DrawerLayout>
+</android.support.v4.widget.DrawerLayout>

+ 9 - 7
src/main/res/values/strings.xml

@@ -205,7 +205,7 @@
     <string name="pass_code_enter_pass_code">Please enter your passcode</string>
     <string name="default_credentials_wrong">Incorrect credentials</string>
     <string name="credentials_disabled">Credentials disabled</string>
-    
+
     <string name="pass_code_configure_your_pass_code">Enter your passcode</string>
     <string name="pass_code_configure_your_pass_code_explanation">The passcode will be requested every time the app is started</string>
     <string name="pass_code_reenter_your_pass_code">Please reenter your passcode</string>
@@ -214,7 +214,7 @@
     <string name="pass_code_wrong">Incorrect passcode</string>
     <string name="pass_code_removed">Passcode deleted</string>
     <string name="pass_code_stored">Passcode stored</string>
-    
+
     <string name="media_notif_ticker">%1$s music player</string>
     <string name="media_state_playing">%1$s (playing)</string>
     <string name="media_state_loading">%1$s (loading)</string>
@@ -294,10 +294,10 @@
     <string name="filedisplay_no_file_selected">No file selected</string>
     <string name="activity_chooser_title">Send link to…</string>
     <string name="wait_for_tmp_copy_from_private_storage">Copying file from private storage</string>
-    
+
     <string name="oauth_check_onoff">Log in with OAuth 2.0</string>
     <string name="oauth_login_connection">Connecting to OAuth 2.0 server…</string>
-        
+
     <string name="ssl_validator_header">The identity of the server could not be verified</string>
     <string name="ssl_validator_reason_cert_not_trusted">- The server certificate is not trusted</string>
     <string name="ssl_validator_reason_cert_expired">- The server certificate expired</string>
@@ -723,7 +723,7 @@
     <string name="notification_channel_file_sync_description">Shows file sync progress and results</string>
     <string name="notification_channel_file_observer_name">File observer</string>
     <string name="notification_channel_file_observer_description">Monitors files for changes</string>
-  
+
     <string name="account_not_found">Account not found!</string>
 
     <string name="screenshot_01_gridView">A safe home for all your data</string>
@@ -732,12 +732,12 @@
     <string name="screenshot_04_accounts">Connect to different accounts</string>
     <string name="screenshot_05_autoUpload">Automatically upload your photos &amp; videos</string>
     <string name="screenshot_06_davdroid">Sync calendar &amp; contacts with DAVdroid</string>
-    
+
     <string name="userinfo_no_info_headline">No personal info set</string>
     <string name="userinfo_no_info_text">Add name, picture and contact details on your profile page.</string>
     <string name="drawer_header_background">Background image of drawer header</string>
     <string name="account_icon">Account icon</string>
-    
+
     <string name="end_to_end_encryption_folder_not_empty">This folder is not empty.</string>
     <string name="end_to_end_encryption_wrong_password">Error while decrypting. Wrong password?</string>
     <string name="end_to_end_encryption_decrypting">Decrypting…</string>
@@ -827,5 +827,7 @@
     <string name="send_note">Send note to recipient</string>
     <string name="note_could_not_sent">Could not send note</string>
     <string name="hint_note">Note</string>
+    <string name="no_browser_available">No app available to handle links</string>
+    <string name="no_pdf_app_available">No App available to handle PDF</string>
 
 </resources>