package com.januschka.twa566271943; import android.app.Activity; import android.content.ComponentName; import android.graphics.Color; import android.net.Uri; import android.os.Bundle; import android.view.Gravity; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import androidx.browser.customtabs.CustomTabsClient; import androidx.browser.customtabs.CustomTabsServiceConnection; import androidx.browser.customtabs.CustomTabsSession; import androidx.browser.trusted.TrustedWebActivityDisplayMode; import androidx.browser.trusted.TrustedWebActivityIntentBuilder; /** * Minimal Trusted Web Activity launcher for Chromium issue 566271943. Binds to the Custom Tabs * service of an installed Chrome/Chromium and launches the hosted probe page as a TWA in either * DefaultMode (display: standalone) or ImmersiveMode (display: fullscreen). */ public class MainActivity extends Activity { private static final String URL = "https://static.januschka.com/i-566271943/twa/index.html"; private static final String[] PROVIDERS = { "org.chromium.chrome", "com.android.chrome", "com.chrome.beta", "com.chrome.dev", "com.chrome.canary", }; private CustomTabsSession mSession; private TextView mStatus; private Button mStandalone; private Button mImmersive; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout root = new LinearLayout(this); root.setOrientation(LinearLayout.VERTICAL); root.setGravity(Gravity.CENTER); root.setBackgroundColor(Color.parseColor("#121212")); int pad = (int) (24 * getResources().getDisplayMetrics().density); root.setPadding(pad, pad, pad, pad); TextView title = new TextView(this); title.setText("TWA sampler for crbug.com/566271943"); title.setTextColor(Color.parseColor("#FFC107")); title.setTextSize(18); title.setGravity(Gravity.CENTER); root.addView(title); mStatus = new TextView(this); mStatus.setTextColor(Color.parseColor("#BEBEBE")); mStatus.setGravity(Gravity.CENTER); mStatus.setPadding(0, pad / 2, 0, pad); mStatus.setText("Connecting to Custom Tabs service..."); root.addView(mStatus); mStandalone = makeButton(root, "Launch standalone TWA (DefaultMode)"); mStandalone.setOnClickListener( v -> launch(new TrustedWebActivityDisplayMode.DefaultMode())); mImmersive = makeButton(root, "Launch immersive TWA (short edges)"); mImmersive.setOnClickListener( v -> launch( new TrustedWebActivityDisplayMode.ImmersiveMode( /* isSticky= */ true, WindowManager.LayoutParams .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES))); setButtonsEnabled(false); setContentView(root); bindProvider(); } private Button makeButton(LinearLayout root, String label) { Button button = new Button(this); button.setText(label); button.setAllCaps(false); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); lp.topMargin = (int) (8 * getResources().getDisplayMetrics().density); root.addView(button, lp); return button; } private void setButtonsEnabled(boolean enabled) { mStandalone.setEnabled(enabled); mImmersive.setEnabled(enabled); } private void bindProvider() { String provider = pickProvider(); if (provider == null) { mStatus.setText("No Custom Tabs provider found. Install Chrome or Chromium."); return; } boolean bound = CustomTabsClient.bindCustomTabsService( this, provider, new CustomTabsServiceConnection() { @Override public void onCustomTabsServiceConnected( ComponentName name, CustomTabsClient client) { client.warmup(0); mSession = client.newSession(null); mStatus.setText("Connected to " + name.getPackageName()); setButtonsEnabled(mSession != null); } @Override public void onServiceDisconnected(ComponentName name) { mSession = null; setButtonsEnabled(false); } }); if (!bound) mStatus.setText("Failed to bind Custom Tabs service of " + provider); } private String pickProvider() { for (String pkg : PROVIDERS) { try { getPackageManager().getPackageInfo(pkg, 0); return pkg; } catch (Exception e) { // Try the next provider. } } return CustomTabsClient.getPackageName(this, null); } private void launch(TrustedWebActivityDisplayMode mode) { if (mSession == null) return; new TrustedWebActivityIntentBuilder(Uri.parse(URL)) .setDisplayMode(mode) .build(mSession) .launchTrustedWebActivity(this); } }