Created
May 6, 2019 05:11
-
-
Save KleversonNascimento/3ca0bf3173f04d3215e7289784666421 to your computer and use it in GitHub Desktop.
LauncherActivity for TWA
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright 2018 Google Inc. All Rights Reserved. | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
package br.com.quintoandar.inquilinos; | |
import android.content.ComponentName; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.content.pm.ActivityInfo; | |
import android.content.pm.PackageInfo; | |
import android.content.pm.PackageManager; | |
import android.content.pm.ResolveInfo; | |
import android.graphics.Color; | |
import android.net.Uri; | |
import android.os.Build; | |
import android.os.Bundle; | |
import android.support.annotation.Nullable; | |
import android.support.customtabs.CustomTabsCallback; | |
import android.support.customtabs.CustomTabsClient; | |
import android.support.customtabs.CustomTabsIntent; | |
import android.support.customtabs.CustomTabsService; | |
import android.support.customtabs.CustomTabsServiceConnection; | |
import android.support.customtabs.CustomTabsSession; | |
import android.support.customtabs.TrustedWebUtils; | |
import android.support.customtabs.trusted.TrustedWebActivityService; | |
import android.support.v4.content.ContextCompat; | |
import android.support.v7.app.AppCompatActivity; | |
import android.util.Log; | |
import android.widget.Toast; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.List; | |
/** | |
* A convenience class to make using Trusted Web Activities easier. You can extend this class for | |
* basic modifications to the behaviour. | |
* | |
* If you just want to wrap a website in a Trusted Web Activity you should: | |
* 1) Copy the manifest for the svgomg project. | |
* 2) Set up Digital Asset Links [1] for your site and app. | |
* 3) Set the DEFAULT_URL metadata in the manifest and the browsable intent filter to point to your | |
* website. | |
* | |
* You can skip (2) if you just want to try out TWAs but not on your own website, but you must | |
* add the {@code --disable-digital-asset-link-verification-for-url=https://svgomg.firebaseapp.com} | |
* to Chrome for this to work [2]. | |
* | |
* You may also go beyond this and add notification delegation, which causes push notifications to | |
* be shown by your app instead of Chrome. This is detailed in the javadoc for | |
* {@link TrustedWebActivityService}. | |
* | |
* If you just want default behaviour your Trusted Web Activity client app doesn't even need any | |
* Java code - you just set everything up in the Android Manifest! | |
* | |
* At the moment this only works with Chrome Dev, Beta and local builds (launch progress [3]). | |
* | |
* [1] https://developers.google.com/digital-asset-links/v1/getting-started | |
* [2] https://www.chromium.org/developers/how-tos/run-chromium-with-flags#TOC-Setting-Flags-for-Chrome-on-Android | |
* [3] https://www.chromestatus.com/feature/4857483210260480 | |
*/ | |
public class LauncherActivity extends AppCompatActivity { | |
private static final String TAG = "LauncherActivity"; | |
private static final String METADATA_DEFAULT_URL = | |
"android.support.customtabs.trusted.DEFAULT_URL"; | |
private static final String METADATA_STATUS_BAR_COLOR = | |
"android.support.customtabs.trusted.STATUS_BAR_COLOR"; | |
private static final String TWA_WAS_LAUNCHED_KEY = | |
"android.support.customtabs.trusted.TWA_WAS_LAUNCHED_KEY"; | |
private static final String STABLE_PACKAGE = "com.android.chrome"; | |
private static final String BETA_PACKAGE = "com.chrome.beta"; | |
private static final String DEV_PACKAGE = "com.chrome.dev"; | |
private static final int SESSION_ID = 96375; | |
private static final String FAKE_URI = "https://www.google.com"; | |
@Nullable private TwaCustomTabsServiceConnection mServiceConnection; | |
@Nullable private String mDefaultUrl; | |
private int mStatusBarColor; | |
private boolean mTwaWasLaunched; | |
private String mCustomTabsProviderPackage; | |
/** We only want to show the update prompt once per instance of this application. */ | |
private static boolean sChromeVersionChecked; | |
/** | |
* Connects to the CustomTabsService. | |
*/ | |
@Override | |
protected void onCreate(@Nullable Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
//Changes init here | |
if(isChromeInstalledAndVersionGreaterThan72()) {//TWA is supported? | |
//TWA is supported! | |
mCustomTabsProviderPackage = CustomTabsClient.getPackageName(this, | |
TrustedWebUtils.SUPPORTED_CHROME_PACKAGES, true); | |
} else { | |
String packageNameCustomTabs = getPackageNameCustomTabs(this); | |
if(packageNameCustomTabs != null) {//Custom Tabs is supported? | |
//Custom Tabs is supported! | |
CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder(); | |
intentBuilder.enableUrlBarHiding(); | |
intentBuilder.setToolbarColor(getResources().getColor(R.color.colorAccent)); | |
CustomTabsIntent customTabsIntent = intentBuilder.build(); | |
customTabsIntent.intent.setPackage(packageNameCustomTabs); | |
customTabsIntent.launchUrl(this, getLaunchingUrl()); | |
} else { | |
//TWA and Custom Tabs not supported | |
Uri fakeUri = Uri.parse(FAKE_URI); | |
Intent shareIntent = new Intent(Intent.ACTION_VIEW, fakeUri); | |
List<ResolveInfo> resInfo; | |
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { | |
resInfo = getPackageManager().queryIntentActivities( | |
shareIntent, PackageManager.MATCH_ALL); | |
} else { | |
resInfo = getPackageManager().queryIntentActivities( | |
shareIntent, 0); | |
} | |
if(!resInfo.isEmpty()) { | |
String packageNameBrowser = resInfo.get(0).activityInfo.packageName; | |
Intent intent = new Intent(Intent.ACTION_VIEW, getLaunchingUrl()); | |
intent.setPackage(packageNameBrowser); | |
startActivity(intent); | |
} | |
} | |
finish(); | |
} | |
//Changes finish here | |
if (mCustomTabsProviderPackage == null) { | |
finish(); | |
return; | |
} | |
if (!sChromeVersionChecked) { | |
sChromeVersionChecked = true; | |
} | |
if (savedInstanceState != null && savedInstanceState.getBoolean(TWA_WAS_LAUNCHED_KEY)) { | |
// This activity died in the background after launching Trusted Web Activity, then | |
// the user closed the Trusted Web Activity and ended up here. | |
finish(); | |
return; | |
} | |
parseMetadata(); | |
mServiceConnection = new TwaCustomTabsServiceConnection(); | |
CustomTabsClient.bindCustomTabsService( | |
this, mCustomTabsProviderPackage, mServiceConnection); | |
} | |
private void parseMetadata() { | |
try { | |
Bundle metaData = getPackageManager().getActivityInfo( | |
new ComponentName(this, getClass()), PackageManager.GET_META_DATA).metaData; | |
if (metaData == null) { | |
return; | |
} | |
mDefaultUrl = metaData.getString(METADATA_DEFAULT_URL); | |
mStatusBarColor = ContextCompat.getColor( | |
this, metaData.getInt(METADATA_STATUS_BAR_COLOR, android.R.color.white)); | |
} catch (PackageManager.NameNotFoundException e) { | |
// Will only happen if the package provided (the one we are running in) is not | |
// installed - so should never happen. | |
} | |
} | |
@Override | |
protected void onRestart() { | |
super.onRestart(); | |
if (mTwaWasLaunched) { | |
finish(); // The user closed the Trusted Web Activity and ended up here. | |
} | |
} | |
@Override | |
protected void onDestroy() { | |
super.onDestroy(); | |
if (mServiceConnection != null) { | |
unbindService(mServiceConnection); | |
} | |
} | |
@Override | |
protected void onSaveInstanceState(Bundle outState) { | |
super.onSaveInstanceState(outState); | |
outState.putBoolean(TWA_WAS_LAUNCHED_KEY, mTwaWasLaunched); | |
} | |
/** | |
* Creates a {@link CustomTabsSession}. Default implementation returns a CustomTabsSession using | |
* a constant session id, see {@link CustomTabsClient#newSession(CustomTabsCallback, int)}, so | |
* that if an instance of Trusted Web Activity associated with this app is already running, the | |
* new Intent will be routed to it, allowing for seamless page transitions. The user will be | |
* able to navigate to the previous page with the back button. | |
* | |
* Override this if you want any special session specific behaviour. To launch separate Trusted | |
* Web Activity instances, return CustomTabsSessions either without session ids (see | |
* {@link CustomTabsClient#newSession(CustomTabsCallback)}) or with different ones on each | |
* call. | |
*/ | |
protected CustomTabsSession getSession(CustomTabsClient client) { | |
return client.newSession(null, SESSION_ID); | |
} | |
/** | |
* Creates a {@link CustomTabsIntent} to launch the Trusted Web Activity. | |
* By default, Trusted Web Activity will be launched in the same Android Task. | |
* Override this if you want any special launching behaviour. | |
*/ | |
protected CustomTabsIntent getCustomTabsIntent(CustomTabsSession session) { | |
return new CustomTabsIntent.Builder(session) | |
.setToolbarColor(mStatusBarColor) | |
.build(); | |
} | |
/** | |
* Returns the URL that the Trusted Web Activity should be launched to. By default this | |
* implementation checks to see if the Activity was launched with an Intent with data, if so | |
* attempt to launch to that URL. If not, read the | |
* "android.support.customtabs.trusted.DEFAULT_URL" metadata from the manifest. | |
* | |
* Override this for special handling (such as ignoring or sanitising data from the Intent). | |
*/ | |
protected Uri getLaunchingUrl() { | |
Uri uri = getIntent().getData(); | |
if (uri != null) { | |
Log.d(TAG, "Using URL from Intent (" + uri + ")."); | |
return uri; | |
} | |
if (mDefaultUrl != null) { | |
Log.d(TAG, "Using URL from Manifest (" + mDefaultUrl + ")."); | |
return Uri.parse(mDefaultUrl); | |
} | |
return Uri.parse("https://www.example.com"); | |
} | |
private class TwaCustomTabsServiceConnection extends CustomTabsServiceConnection { | |
@Override | |
public void onCustomTabsServiceConnected(ComponentName componentName, | |
CustomTabsClient client) { | |
if (TrustedWebUtils.warmupIsRequired( | |
LauncherActivity.this, mCustomTabsProviderPackage)) { | |
client.warmup(0); | |
} | |
CustomTabsSession session = getSession(client); | |
CustomTabsIntent intent = getCustomTabsIntent(session); | |
Uri url = getLaunchingUrl(); | |
Log.d(TAG, "Launching Trusted Web Activity."); | |
TrustedWebUtils.launchAsTrustedWebActivity(LauncherActivity.this, | |
intent, | |
url); | |
// Remember who we connect to as the package that is allowed to delegate notifications | |
// to us. | |
TrustedWebActivityService.setVerifiedProvider( | |
LauncherActivity.this, mCustomTabsProviderPackage); | |
mTwaWasLaunched = true; | |
} | |
@Override | |
public void onServiceDisconnected(ComponentName componentName) { } | |
} | |
private void finishAndRemoveTaskCompat() { | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | |
finishAndRemoveTask(); | |
} else { | |
finish(); | |
} | |
} | |
private String getPackageNameCustomTabs(Context context) { | |
String mPackageNameToUse = null; | |
// Get default VIEW intent handler that can view a web url. | |
Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(FAKE_URI)); | |
// Get all apps that can handle VIEW intents. | |
PackageManager pm = context.getPackageManager(); | |
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()) { | |
mPackageNameToUse = null; | |
} else { | |
mPackageNameToUse = packagesSupportingCustomTabs.get(0); | |
} | |
if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) { | |
mPackageNameToUse = STABLE_PACKAGE; | |
} else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) { | |
mPackageNameToUse = BETA_PACKAGE; | |
} else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) { | |
mPackageNameToUse = DEV_PACKAGE; | |
} | |
return mPackageNameToUse; | |
} | |
private boolean isChromeInstalledAndVersionGreaterThan72() { | |
PackageInfo pInfo; | |
try { | |
pInfo = getPackageManager().getPackageInfo(STABLE_PACKAGE, 0); | |
} catch (PackageManager.NameNotFoundException e) { | |
//chrome is not installed on the device | |
return false; | |
} | |
if (pInfo != null) { | |
//Chrome has versions like 68.0.3440.91, we need to find the major version | |
//using the first dot we find in the string | |
int firstDotIndex = pInfo.versionName.indexOf("."); | |
//take only the number before the first dot excluding the dot itself | |
String majorVersion = pInfo.versionName.substring(0, firstDotIndex); | |
return Integer.parseInt(majorVersion) >= 72; | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment