Ported 'Add repo' intents from FDroid to MainActivity

This commit is contained in:
Peter Serwylo 2017-02-13 14:56:03 +11:00
parent 3bc97d931b
commit 5e6eed9963
2 changed files with 112 additions and 68 deletions

View File

@ -150,74 +150,6 @@
<data android:scheme="fdroidrepos" />
</intent-filter>
<!-- Repo URLs -->
<!--
This intent serves two purposes: Swapping apps between devices and adding a
repo from a website (e.g. https://guardianproject.info/fdroid/repo).
We intercept both of these situations in the FDroid activity, and then redirect
to the appropriate handler (swap handling, manage repos respectively) from there.
The reason for this is that the only differentiating factor is the presence
of a "swap=1" in the query string, and intent-filter is unable to deal with
query parameters. An alternative would be to do something like fdroidswap:// as
a scheme, but then we. Need to copy/paste all of this intent-filter stuff and
keep it up to date when it changes or a bug is found.
-->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<!--
Android's scheme matcher is case-sensitive, so include
ALL CAPS versions to support ALL CAPS URLs in QR Codes.
QR Codes have a special ALL CAPS mode that uses a reduced
character set, making for more compact QR Codes.
-->
<data android:scheme="http" />
<data android:scheme="HTTP" />
<data android:scheme="https" />
<data android:scheme="HTTPS" />
<data android:scheme="fdroidrepo" />
<data android:scheme="FDROIDREPO" />
<data android:scheme="fdroidrepos" />
<data android:scheme="FDROIDREPOS" />
<data android:host="*" />
<!--
The pattern matcher here is poorly implemented, in particular the * is
non-greedy, so you have to do stupid tricks to match patterns that have
repeat characters in them. http://stackoverflow.com/a/8599921/306864
-->
<data android:path="/fdroid/repo" />
<data android:pathPattern="/fdroid/repo/*" />
<data android:pathPattern="/.*/fdroid/repo" />
<data android:pathPattern="/.*/fdroid/repo/*" />
<data android:pathPattern="/.*/.*/fdroid/repo" />
<data android:pathPattern="/.*/.*/fdroid/repo/*" />
<data android:pathPattern="/.*/.*/.*/fdroid/repo" />
<data android:pathPattern="/.*/.*/.*/fdroid/repo/*" />
<data android:path="/fdroid/archive" />
<data android:pathPattern="/fdroid/archive/*" />
<data android:pathPattern="/.*/fdroid/archive" />
<data android:pathPattern="/.*/fdroid/archive/*" />
<data android:pathPattern="/.*/.*/fdroid/archive" />
<data android:pathPattern="/.*/.*/fdroid/archive/*" />
<data android:pathPattern="/.*/.*/.*/fdroid/archive" />
<data android:pathPattern="/.*/.*/.*/fdroid/archive/*" />
<!--
Some QR Code scanners don't respect custom schemes like fdroidrepo://,
so this is a workaround, since the local repo URL is all uppercase in
the QR Code for sending the local repo to another device.
-->
<data android:path="/FDROID/REPO" />
<data android:pathPattern="/.*/FDROID/REPO" />
<data android:pathPattern="/.*/.*/FDROID/REPO" />
<data android:pathPattern="/.*/.*/.*/FDROID/REPO" />
</intent-filter>
</activity>
<activity
android:name=".privileged.views.InstallConfirmActivity"
@ -510,6 +442,75 @@
android:name="android.app.searchable"
android:resource="@xml/searchable" />
<!-- Repo URLs -->
<!--
This intent serves two purposes: Swapping apps between devices and adding a
repo from a website (e.g. https://guardianproject.info/fdroid/repo).
We intercept both of these situations in the FDroid activity, and then redirect
to the appropriate handler (swap handling, manage repos respectively) from there.
The reason for this is that the only differentiating factor is the presence
of a "swap=1" in the query string, and intent-filter is unable to deal with
query parameters. An alternative would be to do something like fdroidswap:// as
a scheme, but then we need to copy/paste all of this intent-filter stuff and
keep it up to date when it changes or a bug is found.
-->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<!--
Android's scheme matcher is case-sensitive, so include
ALL CAPS versions to support ALL CAPS URLs in QR Codes.
QR Codes have a special ALL CAPS mode that uses a reduced
character set, making for more compact QR Codes.
-->
<data android:scheme="http" />
<data android:scheme="HTTP" />
<data android:scheme="https" />
<data android:scheme="HTTPS" />
<data android:scheme="fdroidrepo" />
<data android:scheme="FDROIDREPO" />
<data android:scheme="fdroidrepos" />
<data android:scheme="FDROIDREPOS" />
<data android:host="*" />
<!--
The pattern matcher here is poorly implemented, in particular the * is
non-greedy, so you have to do stupid tricks to match patterns that have
repeat characters in them. http://stackoverflow.com/a/8599921/306864
-->
<data android:path="/fdroid/repo" />
<data android:pathPattern="/fdroid/repo/*" />
<data android:pathPattern="/.*/fdroid/repo" />
<data android:pathPattern="/.*/fdroid/repo/*" />
<data android:pathPattern="/.*/.*/fdroid/repo" />
<data android:pathPattern="/.*/.*/fdroid/repo/*" />
<data android:pathPattern="/.*/.*/.*/fdroid/repo" />
<data android:pathPattern="/.*/.*/.*/fdroid/repo/*" />
<data android:path="/fdroid/archive" />
<data android:pathPattern="/fdroid/archive/*" />
<data android:pathPattern="/.*/fdroid/archive" />
<data android:pathPattern="/.*/fdroid/archive/*" />
<data android:pathPattern="/.*/.*/fdroid/archive" />
<data android:pathPattern="/.*/.*/fdroid/archive/*" />
<data android:pathPattern="/.*/.*/.*/fdroid/archive" />
<data android:pathPattern="/.*/.*/.*/fdroid/archive/*" />
<!--
Some QR Code scanners don't respect custom schemes like fdroidrepo://,
so this is a workaround, since the local repo URL is all uppercase in
the QR Code for sending the local repo to another device.
-->
<data android:path="/FDROID/REPO" />
<data android:pathPattern="/.*/FDROID/REPO" />
<data android:pathPattern="/.*/.*/FDROID/REPO" />
<data android:pathPattern="/.*/.*/.*/FDROID/REPO" />
</intent-filter>
</activity>
<activity android:name=".views.apps.AppListActivity" />

View File

@ -12,6 +12,7 @@ import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.text.TextUtils;
import android.view.MenuItem;
import android.widget.Toast;
import android.support.v7.widget.RecyclerView;
import org.fdroid.fdroid.AppDetails;
@ -22,7 +23,10 @@ import org.fdroid.fdroid.R;
import org.fdroid.fdroid.UpdateService;
import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.compat.UriCompat;
import org.fdroid.fdroid.data.NewRepoConfig;
import org.fdroid.fdroid.views.ManageReposActivity;
import org.fdroid.fdroid.views.apps.AppListActivity;
import org.fdroid.fdroid.views.swap.SwapWorkflowActivity;
/**
* Main view shown to users upon starting F-Droid.
@ -44,6 +48,12 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationV
public static final String EXTRA_VIEW_MY_APPS = "org.fdroid.fdroid.views.main.MainActivity.VIEW_MY_APPS";
private static final String ADD_REPO_INTENT_HANDLED = "addRepoIntentHandled";
private static final String ACTION_ADD_REPO = "org.fdroid.fdroid.MainActivity.ACTION_ADD_REPO";
private static final int REQUEST_SWAP = 3;
private RecyclerView pager;
private MainViewAdapter adapter;
@ -98,12 +108,24 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationV
// AppDetails 2 and RepoDetailsActivity set different NFC actions, so reset here
NfcHelper.setAndroidBeam(this, getApplication().getPackageName());
checkForAddRepoIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleSearchOrAppViewIntent(intent);
// This is called here as well as onResume(), because onNewIntent() is not called the first
// time the activity is created. An alternative option to make sure that the add repo intent
// is always handled is to call setIntent(intent) here. However, after this good read:
// http://stackoverflow.com/a/7749347 it seems that adding a repo is not really more
// important than the original intent which caused the activity to start (even though it
// could technically have been an add repo intent itself).
// The end result is that this method will be called twice for one add repo intent. Once
// here and once in onResume(). However, the method deals with this by ensuring it only
// handles the same intent once.
checkForAddRepoIntent(intent);
}
@Override
@ -216,6 +238,27 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationV
startActivity(searchIntent);
}
private void checkForAddRepoIntent(Intent intent) {
// Don't handle the intent after coming back to this view (e.g. after hitting the back button)
// http://stackoverflow.com/a/14820849
if (!intent.hasExtra(ADD_REPO_INTENT_HANDLED)) {
intent.putExtra(ADD_REPO_INTENT_HANDLED, true);
NewRepoConfig parser = new NewRepoConfig(this, intent);
if (parser.isValidRepo()) {
if (parser.isFromSwap()) {
Intent confirmIntent = new Intent(this, SwapWorkflowActivity.class);
confirmIntent.putExtra(SwapWorkflowActivity.EXTRA_CONFIRM, true);
confirmIntent.setData(intent.getData());
startActivityForResult(confirmIntent, REQUEST_SWAP);
} else {
startActivity(new Intent(ACTION_ADD_REPO, intent.getData(), this, ManageReposActivity.class));
}
} else if (parser.getErrorMessage() != null) {
Toast.makeText(this, parser.getErrorMessage(), Toast.LENGTH_LONG).show();
}
}
}
private static class NonScrollingHorizontalLayoutManager extends LinearLayoutManager {
NonScrollingHorizontalLayoutManager(Context context) {
super(context, LinearLayoutManager.HORIZONTAL, false);