1
0
Fork 0
mirror of https://github.com/gsantner/dandelion synced 2024-06-13 23:24:54 +02:00

Merge pull request #67 from Diaspora-for-Android/customTabs

Custom tabs
This commit is contained in:
Gregor Santner 2016-09-18 20:26:35 +02:00 committed by GitHub
commit ef0e1b792a
9 changed files with 481 additions and 58 deletions

View file

@ -48,6 +48,7 @@ dependencies {
compile 'com.jakewharton:butterknife:8.0.1'
compile 'info.guardianproject.netcipher:netcipher:2.0.0-alpha1'
compile 'info.guardianproject.netcipher:netcipher-webkit:2.0.0-alpha1'
compile "com.android.support:customtabs:24.2.0"
apt 'com.jakewharton:butterknife-compiler:8.0.1'
}

View file

@ -26,6 +26,8 @@ import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.graphics.drawable.LayerDrawable;
import android.support.v4.view.MenuItemCompat;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -33,7 +35,7 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.drawable.LayerDrawable;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@ -42,12 +44,12 @@ import android.os.Handler;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.customtabs.CustomTabsIntent;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
@ -79,9 +81,13 @@ import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.data.AppSettings;
import com.github.dfa.diaspora_android.data.PodUserProfile;
import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener;
import com.github.dfa.diaspora_android.receivers.OpenExternalLinkReceiver;
import com.github.dfa.diaspora_android.receivers.UpdateTitleReceiver;
import com.github.dfa.diaspora_android.ui.BadgeDrawable;
import com.github.dfa.diaspora_android.ui.ContextMenuWebView;
import com.github.dfa.diaspora_android.ui.CustomWebViewClient;
import com.github.dfa.diaspora_android.util.CustomTabHelpers.BrowserFallback;
import com.github.dfa.diaspora_android.util.CustomTabHelpers.CustomTabActivityHelper;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
import com.github.dfa.diaspora_android.util.Helpers;
import com.github.dfa.diaspora_android.util.Log;
@ -114,6 +120,7 @@ public class MainActivity extends AppCompatActivity
public static final int REQUEST_CODE__ACCESS_EXTERNAL_STORAGE = 124;
public static final String ACTION_OPEN_URL = "com.github.dfa.diaspora_android.MainActivity.open_url";
public static final String ACTION_OPEN_EXTERNAL_URL = "com.github.dfa.diaspora_android.MainActivity.open_external_url";
public static final String ACTION_CHANGE_ACCOUNT = "com.github.dfa.diaspora_android.MainActivity.change_account";
public static final String ACTION_CLEAR_CACHE = "com.github.dfa.diaspora_android.MainActivity.clear_cache";
public static final String ACTION_UPDATE_TITLE_FROM_URL = "com.github.dfa.diaspora_android.MainActivity.set_title";
@ -126,12 +133,15 @@ public class MainActivity extends AppCompatActivity
private ValueCallback<Uri[]> imageUploadFilePathCallbackNew;
private ValueCallback<Uri> imageUploadFilePathCallbackOld;
private String mCameraPhotoPath;
private CustomTabActivityHelper customTabActivityHelper;
private WebSettings webSettings;
private AppSettings appSettings;
private DiasporaUrlHelper urls;
private PodUserProfile podUserProfile;
private final Handler uiHandler = new Handler();
private CustomWebViewClient webViewClient;
private OpenExternalLinkReceiver brOpenExternalLink;
private BroadcastReceiver brSetTitle;
private Snackbar snackbarExitApp;
private Snackbar snackbarNewNotification;
private Snackbar snackbarNoInternet;
@ -189,6 +199,7 @@ public class MainActivity extends AppCompatActivity
podUserProfile.setCallbackHandler(uiHandler);
podUserProfile.setListener(this);
urls = new DiasporaUrlHelper(appSettings);
customTabActivityHelper = new CustomTabActivityHelper();
setupUI(savedInstanceState);
@ -200,24 +211,42 @@ public class MainActivity extends AppCompatActivity
} else if (appSettings.wasProxyEnabled()) {
resetProxy();
}
brOpenExternalLink = new OpenExternalLinkReceiver(this);
brSetTitle = new UpdateTitleReceiver(app, urls, new UpdateTitleReceiver.TitleCallback() {
@Override
public void setTitle(int rId) {
MainActivity.this.setTitle(rId);
}
@Override
public void setTitle(String title) {
MainActivity.this.setTitle(title);
}
});
}
private void setupUI(Bundle savedInstanceState) {
Log.i(App.TAG, "MainActivity.setupUI()");
ButterKnife.bind(this);
if (webviewPlaceholder.getChildCount() != 0) {
Log.v(App.TAG, "remove child views from webViewPlaceholder");
webviewPlaceholder.removeAllViews();
} else {
Log.v(App.TAG, "webViewPlaceholder had no child views");
}
boolean newWebView = (webView == null);
if(newWebView) {
Log.v(App.TAG, "Webview was null. Create new one.");
Log.v(App.TAG, "WebView was null. Create new one.");
View webviewHolder = getLayoutInflater().inflate(R.layout.webview, this.contentLayout, false);
webView = (ContextMenuWebView) webviewHolder.findViewById(R.id.webView);
this.webView = (ContextMenuWebView) webviewHolder.findViewById(R.id.webView);
((LinearLayout)webView.getParent()).removeView(webView);
setupWebView(savedInstanceState);
} else {
Log.v(App.TAG, "Reuse old WebView to avoid reloading page");
}
ButterKnife.bind(this);
if (webviewPlaceholder.getChildCount() != 0) {
webviewPlaceholder.removeAllViews();
}
Log.v(App.TAG, "Add WebView to placeholder");
webviewPlaceholder.addView(webView);
// Setup toolbar
@ -689,52 +718,24 @@ public class MainActivity extends AppCompatActivity
}
}
/**
* BroadcastReceiver that updates the title of the activity based on which url is currently loaded
*/
private final BroadcastReceiver brSetTitle = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String url = intent.getStringExtra(EXTRA_URL);
if (url != null && url.startsWith(urls.getPodUrl())) {
String subUrl = url.substring((urls.getPodUrl()).length());
Log.v(App.TAG, "MainActivity.brSetTitle.onReceive(): Set title for subUrl "+subUrl);
if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_STREAM)) {
setTitle(R.string.nav_stream);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_POSTS)) {
setTitle(R.string.diaspora);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_NOTIFICATIONS)) {
setTitle(R.string.notifications);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_CONVERSATIONS)) {
setTitle(R.string.conversations);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_NEW_POST)) {
setTitle(R.string.new_post);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_PEOPLE + appSettings.getProfileId())) {
setTitle(R.string.nav_profile);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_ACTIVITY)) {
setTitle(R.string.nav_activities);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_LIKED)) {
setTitle(R.string.nav_liked);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_COMMENTED)) {
setTitle(R.string.nav_commented);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_MENTIONS)) {
setTitle(R.string.nav_mentions);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_PUBLIC)) {
setTitle(R.string.public_);
} else if (urls.isAspectUrl(url)){
setTitle(urls.getAspectNameFromUrl(url, app));
}
} else {
Log.w(App.TAG, "MainActivity.brSetTitle.onReceive(): Invalid url: "+url);
}
}
};
@Override
protected void onStart() {
super.onStart();
customTabActivityHelper.bindCustomTabsService(this);
}
@Override
protected void onStop() {
super.onStop();
customTabActivityHelper.unbindCustomTabsService(this);
}
@Override
protected void onPause() {
Log.v(App.TAG, "MainActivity.onPause()");
Log.v(App.TAG, "Unregister BroadcastReceivers");
LocalBroadcastManager.getInstance(this).unregisterReceiver(brSetTitle);
LocalBroadcastManager.getInstance(this).unregisterReceiver(brOpenExternalLink);
super.onPause();
}
@ -744,19 +745,20 @@ public class MainActivity extends AppCompatActivity
super.onResume();
Log.v(App.TAG, "Register BroadcastReceivers");
LocalBroadcastManager.getInstance(this).registerReceiver(brSetTitle, new IntentFilter(ACTION_UPDATE_TITLE_FROM_URL));
LocalBroadcastManager.getInstance(this).registerReceiver(brOpenExternalLink, new IntentFilter(ACTION_OPEN_EXTERNAL_URL));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
Log.v(App.TAG, "MainActivity.onCreateOptionsMenu()");
getMenuInflater().inflate(R.menu.main__menu_top, menu);
return super.onCreateOptionsMenu(menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
Log.i(App.TAG, "MainActivity.onPrepareOptionsMenu()");
MenuItem item;
if ((item = menu.findItem(R.id.action_notifications)) != null) {
LayerDrawable icon = (LayerDrawable) item.getIcon();
BadgeDrawable.setBadgeCount(this, icon, podUserProfile.getNotificationCount());

View file

@ -0,0 +1,50 @@
package com.github.dfa.diaspora_android.receivers;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.support.customtabs.CustomTabsIntent;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.activity.MainActivity;
import com.github.dfa.diaspora_android.util.CustomTabHelpers.BrowserFallback;
import com.github.dfa.diaspora_android.util.CustomTabHelpers.CustomTabActivityHelper;
import com.github.dfa.diaspora_android.util.Log;
/**
* BroadcastReceiver that opens links in a Chrome CustomTab
* Created by vanitas on 11.09.16.
*/
public class OpenExternalLinkReceiver extends BroadcastReceiver {
private final Activity parent;
public OpenExternalLinkReceiver(Activity parent) {
this.parent = parent;
}
@Override
public void onReceive(Context context, Intent intent) {
String url = intent.getStringExtra(MainActivity.EXTRA_URL);
Log.v(App.TAG, "OpenExternalLinkReceiver.onReceive(): url");
if(url != null) {
CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder();
if(Build.VERSION.SDK_INT >= 23) {
intentBuilder.setToolbarColor(context.getResources().getColor(R.color.colorPrimary, context.getTheme()));
} else {
intentBuilder.setToolbarColor(context.getResources().getColor(R.color.colorPrimary));
}
intentBuilder.setStartAnimations(context, android.R.anim.slide_in_left, android.R.anim.fade_out);
intentBuilder.setExitAnimations(context, android.R.anim.fade_in, android.R.anim.slide_out_right);
Bitmap backButtonIcon = BitmapFactory.decodeResource(context.getResources(),
R.drawable.ic_arrow_back_white_24px);
intentBuilder.setCloseButtonIcon(backButtonIcon);
CustomTabActivityHelper.openCustomTab(parent, intentBuilder.build(), Uri.parse(url), new BrowserFallback());
}
}
}

View file

@ -0,0 +1,79 @@
package com.github.dfa.diaspora_android.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.activity.MainActivity;
import com.github.dfa.diaspora_android.data.AppSettings;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
import com.github.dfa.diaspora_android.util.Log;
/**
* BroadcastReceiver used to update the title of the MainActivity depending on the url of the webview
* Created by vanitas on 11.09.16.
*/
public class UpdateTitleReceiver extends BroadcastReceiver {
private DiasporaUrlHelper urls;
private AppSettings appSettings;
private App app;
private TitleCallback callback;
public UpdateTitleReceiver(App app, DiasporaUrlHelper urls, TitleCallback callback) {
this.urls = urls;
this.app = app;
this.appSettings = app.getSettings();
this.callback = callback;
}
@Override
public void onReceive(Context context, Intent intent) {
String url = intent.getStringExtra(MainActivity.EXTRA_URL);
if (url != null && url.startsWith(urls.getPodUrl())) {
String subUrl = url.substring((urls.getPodUrl()).length());
Log.v(App.TAG, "UpdateTitleReceiver.onReceive(): Set title for subUrl "+subUrl);
if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_STREAM)) {
setTitle(R.string.nav_stream);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_POSTS)) {
setTitle(R.string.diaspora);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_NOTIFICATIONS)) {
setTitle(R.string.notifications);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_CONVERSATIONS)) {
setTitle(R.string.conversations);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_NEW_POST)) {
setTitle(R.string.new_post);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_PEOPLE + appSettings.getProfileId())) {
setTitle(R.string.nav_profile);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_ACTIVITY)) {
setTitle(R.string.nav_activities);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_LIKED)) {
setTitle(R.string.nav_liked);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_COMMENTED)) {
setTitle(R.string.nav_commented);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_MENTIONS)) {
setTitle(R.string.nav_mentions);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_PUBLIC)) {
setTitle(R.string.public_);
} else if (urls.isAspectUrl(url)){
setTitle(urls.getAspectNameFromUrl(url, app));
}
} else {
Log.w(App.TAG, "UpdateTitleReceiver.onReceive(): Invalid url: "+url);
}
}
private void setTitle(int rId) {
callback.setTitle(rId);
}
private void setTitle(String title) {
callback.setTitle(title);
}
public interface TitleCallback {
void setTitle(int Rid);
void setTitle(String title);
}
}

View file

@ -20,11 +20,13 @@ package com.github.dfa.diaspora_android.ui;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.content.LocalBroadcastManager;
import android.webkit.CookieManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.activity.MainActivity;
public class CustomWebViewClient extends WebViewClient {
private final App app;
@ -37,9 +39,9 @@ public class CustomWebViewClient extends WebViewClient {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (!url.contains(app.getSettings().getPodDomain())) {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
app.getApplicationContext().startActivity(i);
Intent i = new Intent(MainActivity.ACTION_OPEN_EXTERNAL_URL);
i.putExtra(MainActivity.EXTRA_URL, url);
LocalBroadcastManager.getInstance(app.getApplicationContext()).sendBroadcast(i);
return true;
}
return false;

View file

@ -0,0 +1,18 @@
package com.github.dfa.diaspora_android.util.CustomTabHelpers;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
/**
* Adapted from https://medium.com/ribot-labs/exploring-chrome-customs-tabs-on-android-ef427effe2f4
*/
public class BrowserFallback implements CustomTabActivityHelper.CustomTabFallback {
@Override
public void openUri(Activity activity, Uri uri) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
activity.startActivity(intent);
}
}

View file

@ -0,0 +1,149 @@
package com.github.dfa.diaspora_android.util.CustomTabHelpers;
import android.app.Activity;
import android.content.ComponentName;
import android.net.Uri;
import android.os.Bundle;
import android.support.customtabs.CustomTabsClient;
import android.support.customtabs.CustomTabsIntent;
import android.support.customtabs.CustomTabsServiceConnection;
import android.support.customtabs.CustomTabsSession;
import android.util.Log;
import java.util.List;
/**
* Adapted from https://medium.com/ribot-labs/exploring-chrome-customs-tabs-on-android-ef427effe2f4
*/
public class CustomTabActivityHelper {
private CustomTabsSession mCustomTabsSession;
private CustomTabsClient mClient;
private CustomTabsServiceConnection mConnection;
private ConnectionCallback mConnectionCallback;
/**
* Opens the URL on a Custom Tab if possible. Otherwise fallsback to opening it on a WebView
*
* @param activity The host activity
* @param customTabsIntent a CustomTabsIntent to be used if Custom Tabs is available
* @param uri the Uri to be opened
* @param fallback a CustomTabFallback to be used if Custom Tabs is not available
*/
public static void openCustomTab(Activity activity,
CustomTabsIntent customTabsIntent,
Uri uri,
CustomTabFallback fallback) {
String packageName = CustomTabsHelper.getPackageNameToUse(activity);
//If we cant find a package name, it means there's no browser that supports
//Chrome Custom Tabs installed. So, we fallback to the webview
if (packageName == null) {
if (fallback != null) {
fallback.openUri(activity, uri);
}
} else {
customTabsIntent.intent.setPackage(packageName);
customTabsIntent.launchUrl(activity, uri);
}
}
/**
* Unbinds the Activity from the Custom Tabs Service
* @param activity the activity that is connected to the service
*/
public void unbindCustomTabsService(Activity activity) {
if (mConnection == null) return;
activity.unbindService(mConnection);
mClient = null;
mCustomTabsSession = null;
}
/**
* Creates or retrieves an exiting CustomTabsSession
*
* @return a CustomTabsSession
*/
public CustomTabsSession getSession() {
if (mClient == null) {
mCustomTabsSession = null;
} else if (mCustomTabsSession == null) {
mCustomTabsSession = mClient.newSession(null);
}
return mCustomTabsSession;
}
/**
* Register a Callback to be called when connected or disconnected from the Custom Tabs Service
* @param connectionCallback
*/
public void setConnectionCallback(ConnectionCallback connectionCallback) {
this.mConnectionCallback = connectionCallback;
}
/**
* Binds the Activity to the Custom Tabs Service
* @param activity the activity to be binded to the service
*/
public void bindCustomTabsService(Activity activity) {
if (mClient != null) return;
String packageName = CustomTabsHelper.getPackageNameToUse(activity);
if (packageName == null) return;
mConnection = new CustomTabsServiceConnection() {
@Override
public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
mClient = client;
mClient.warmup(0L);
if (mConnectionCallback != null) mConnectionCallback.onCustomTabsConnected();
//Initialize a session as soon as possible.
getSession();
}
@Override
public void onServiceDisconnected(ComponentName name) {
mClient = null;
if (mConnectionCallback != null) mConnectionCallback.onCustomTabsDisconnected();
}
};
CustomTabsClient.bindCustomTabsService(activity, packageName, mConnection);
}
public boolean mayLaunchUrl(Uri uri, Bundle extras, List<Bundle> otherLikelyBundles) {
if (mClient == null) return false;
CustomTabsSession session = getSession();
if (session == null) return false;
return session.mayLaunchUrl(uri, extras, otherLikelyBundles);
}
/**
* A Callback for when the service is connected or disconnected. Use those callbacks to
* handle UI changes when the service is connected or disconnected
*/
public interface ConnectionCallback {
/**
* Called when the service is connected
*/
void onCustomTabsConnected();
/**
* Called when the service is disconnected
*/
void onCustomTabsDisconnected();
}
/**
* To be used as a fallback to open the Uri when Custom Tabs is not available
*/
public interface CustomTabFallback {
/**
*
* @param activity The Activity that wants to open the Uri
* @param uri The uri to be opened by the fallback
*/
void openUri(Activity activity, Uri uri);
}
}

View file

@ -0,0 +1,121 @@
package com.github.dfa.diaspora_android.util.CustomTabHelpers;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.support.customtabs.CustomTabsService;
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
/**
* Helper class for Custom Tabs. Adapted from https://medium.com/ribot-labs/exploring-chrome-customs-tabs-on-android-ef427effe2f4
*/
public class CustomTabsHelper {
private static final String TAG = "CustomTabsHelper";
static final String STABLE_PACKAGE = "com.android.chrome";
static final String BETA_PACKAGE = "com.chrome.beta";
static final String DEV_PACKAGE = "com.chrome.dev";
static final String LOCAL_PACKAGE = "com.google.android.apps.chrome";
private static final String EXTRA_CUSTOM_TABS_KEEP_ALIVE =
"android.support.customtabs.extra.KEEP_ALIVE";
private static String sPackageNameToUse;
private CustomTabsHelper() {}
/**
* Goes through all apps that handle VIEW intents and have a warmup service. Picks
* the one chosen by the user if there is one, otherwise makes a best effort to return a
* valid package name.
*
* This is <strong>not</strong> threadsafe.
*
* @param context {@link Context} to use for accessing {@link PackageManager}.
* @return The package name recommended to use for connecting to custom tabs related components.
*/
public static String getPackageNameToUse(Context context) {
if (sPackageNameToUse != null) return sPackageNameToUse;
PackageManager pm = context.getPackageManager();
// Get default VIEW intent handler.
Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
ResolveInfo defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0);
String defaultViewHandlerPackageName = null;
if (defaultViewHandlerInfo != null) {
defaultViewHandlerPackageName = defaultViewHandlerInfo.activityInfo.packageName;
}
// Get all apps that can handle VIEW intents.
List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
List<String> packagesSupportingCustomTabs = new ArrayList<>();
for (ResolveInfo info : resolvedActivityList) {
Intent serviceIntent = new Intent();
serviceIntent.setAction(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION);
serviceIntent.setPackage(info.activityInfo.packageName);
if (pm.resolveService(serviceIntent, 0) != null) {
packagesSupportingCustomTabs.add(info.activityInfo.packageName);
}
}
// Now packagesSupportingCustomTabs contains all apps that can handle both VIEW intents
// and service calls.
if (packagesSupportingCustomTabs.isEmpty()) {
sPackageNameToUse = null;
} else if (packagesSupportingCustomTabs.size() == 1) {
sPackageNameToUse = packagesSupportingCustomTabs.get(0);
} else if (!TextUtils.isEmpty(defaultViewHandlerPackageName)
&& !hasSpecializedHandlerIntents(context, activityIntent)
&& packagesSupportingCustomTabs.contains(defaultViewHandlerPackageName)) {
sPackageNameToUse = defaultViewHandlerPackageName;
} else if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) {
sPackageNameToUse = STABLE_PACKAGE;
} else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) {
sPackageNameToUse = BETA_PACKAGE;
} else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) {
sPackageNameToUse = DEV_PACKAGE;
} else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) {
sPackageNameToUse = LOCAL_PACKAGE;
}
return sPackageNameToUse;
}
/**
* Used to check whether there is a specialized handler for a given intent.
* @param intent The intent to check with.
* @return Whether there is a specialized handler for the given intent.
*/
private static boolean hasSpecializedHandlerIntents(Context context, Intent intent) {
try {
PackageManager pm = context.getPackageManager();
List<ResolveInfo> handlers = pm.queryIntentActivities(
intent,
PackageManager.GET_RESOLVED_FILTER);
if (handlers == null || handlers.size() == 0) {
return false;
}
for (ResolveInfo resolveInfo : handlers) {
IntentFilter filter = resolveInfo.filter;
if (filter == null) continue;
if (filter.countDataAuthorities() == 0 || filter.countDataPaths() == 0) continue;
if (resolveInfo.activityInfo == null) continue;
return true;
}
} catch (RuntimeException e) {
Log.e(TAG, "Runtime exception while getting specialized handlers");
}
return false;
}
/**
* @return All possible chrome package names that provide custom tabs feature.
*/
public static String[] getPackages() {
return new String[]{"", STABLE_PACKAGE, BETA_PACKAGE, DEV_PACKAGE, LOCAL_PACKAGE};
}
}

View file

@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.github.dfa.diaspora_android.ui.ContextMenuWebView
android:id="@+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
android:layout_height="fill_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true" />
</LinearLayout>