Skip to content
173 changes: 156 additions & 17 deletions app/src/main/java/me/ghui/v2er/module/vshare/VshareWebActivity.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
package me.ghui.v2er.module.vshare;

import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.annotation.Nullable;

import butterknife.BindView;
import butterknife.ButterKnife;
import me.ghui.v2er.R;
import me.ghui.v2er.module.base.BaseActivity;
import me.ghui.v2er.module.base.BaseContract;
import me.ghui.v2er.util.DarkModelUtils;
import me.ghui.v2er.widget.BaseToolBar;

/**
* Fullscreen WebView Activity for displaying vshare page
* with automatic theme adaptation
*/
public class VshareWebActivity extends AppCompatActivity {
public class VshareWebActivity extends BaseActivity<BaseContract.IPresenter> {

private static final String TAG = "VshareWebActivity";
private static final String VSHARE_BASE_URL = "https://v2er.app/vshare";

@BindView(R.id.webview)
Expand All @@ -40,18 +49,36 @@ public static void open(Context context) {
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
protected int attachLayoutRes() {
return R.layout.activity_vshare_web;
}

// Hide action bar if present
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
}
@Nullable
@Override
protected BaseToolBar attachToolbar() {
// Return null to hide the toolbar for fullscreen WebView experience
return null;
}

// Set SystemUI flags to match MainActivity's edge-to-edge behavior
@Override
protected void reloadMode(int mode) {
// Recreate activity to apply new theme
recreate();
}

@Override
protected boolean supportSlideBack() {
// Disable slide back for fullscreen WebView
return false;
}

@Override
protected void init() {
super.init();

// Apply fullscreen flags for edge-to-edge WebView
View decorView = getWindow().getDecorView();
int systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
int systemUiVisibility = decorView.getSystemUiVisibility()
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;

// Set status bar icon color based on theme
Expand All @@ -64,8 +91,8 @@ protected void onCreate(Bundle savedInstanceState) {

decorView.setSystemUiVisibility(systemUiVisibility);

setContentView(R.layout.activity_vshare_web);
ButterKnife.bind(this);
// Set WebView top margin to status bar height
applyStatusBarMargin();

setupWebView();

Expand Down Expand Up @@ -114,8 +141,12 @@ private void setupWebView() {
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
// Let the WebView handle the navigation
return false;
return handleUrlLoading(request.getUrl().toString());
}

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return handleUrlLoading(url);
}

@Override
Expand Down Expand Up @@ -149,6 +180,114 @@ public void onProgressChanged(WebView view, int newProgress) {
});
}

/**
* Apply status bar height as top margin to WebView
*/
private void applyStatusBarMargin() {
int statusBarHeight = getStatusBarHeight();
if (statusBarHeight > 0) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mWebView.getLayoutParams();
if (params instanceof FrameLayout.LayoutParams) {
params.topMargin = statusBarHeight;
mWebView.setLayoutParams(params);
}
}
}

/**
* Get status bar height dynamically
*/
private int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}

/**
* Handle URL loading for WebView
* Returns true if the URL was handled externally, false if WebView should load it
*/
private boolean handleUrlLoading(String url) {
if (url == null) {
return false;
}

Uri uri = Uri.parse(url);
String scheme = uri.getScheme();

// Handle intent:// URLs (e.g., Google Play Store links)
if ("intent".equals(scheme)) {
try {
Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);

// Check if there's an app that can handle this intent
if (getPackageManager().resolveActivity(intent, 0) != null) {
Copy link

Copilot AI Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resolveActivity() call with flags=0 is deprecated in API level 30+. Use PackageManager.ResolveInfo flags or PackageManager.MATCH_DEFAULT_ONLY for better compatibility.

Copilot uses AI. Check for mistakes.
startActivity(intent);
return true;
}

// Fallback: Try to open the browser_fallback_url if available
String fallbackUrl = intent.getStringExtra("browser_fallback_url");
if (fallbackUrl != null) {
mWebView.loadUrl(fallbackUrl);
return true;
}

// Last resort: Try to open in Google Play if it's a Play Store intent
String packageName = intent.getPackage();
if (packageName != null) {
Intent marketIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse("market://details?id=" + packageName));
marketIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (getPackageManager().resolveActivity(marketIntent, 0) != null) {
Copy link

Copilot AI Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resolveActivity() call with flags=0 is deprecated in API level 30+. Use PackageManager.ResolveInfo flags or PackageManager.MATCH_DEFAULT_ONLY for better compatibility.

Copilot uses AI. Check for mistakes.
startActivity(marketIntent);
return true;
}
}
} catch (Exception e) {
Log.e(TAG, "Error handling intent URL: " + url, e);
Toast.makeText(this, "Unable to open app", Toast.LENGTH_SHORT).show();
}
return true;
}

// Handle market:// URLs (Google Play Store)
if ("market".equals(scheme)) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
return true;
} catch (ActivityNotFoundException e) {
Log.e(TAG, "Google Play Store not found", e);
// Fallback to web version
String webUrl = url.replace("market://", "https://play.google.com/store/apps/");
mWebView.loadUrl(webUrl);
return true;
}
}

// Handle other app-specific schemes (e.g., mailto:, tel:, etc.)
if (!"http".equals(scheme) && !"https".equals(scheme)) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
return true;
} catch (ActivityNotFoundException e) {
Log.e(TAG, "No app found to handle scheme: " + scheme, e);
Toast.makeText(this, "No app found to open this link", Toast.LENGTH_SHORT).show();
return true;
}
}

// Let WebView handle normal http/https URLs
return false;
}

@Override
public void onBackPressed() {
// Handle back navigation in WebView
Expand All @@ -170,4 +309,4 @@ protected void onDestroy() {
}
super.onDestroy();
}
}
}
Loading