Rev 5 | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
package com.cesams.leaderslinked.v2;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import android.Manifest;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import android.content.pm.PackageManager;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private TouchyWebView mWebView = null;
private SwipeRefreshLayout mSwipeRefreshLayout;
private static final String file_type = "*/*";
private ValueCallback<Uri[]> file_path;
private final static String _URL = BuildConfig.BASE_URL;
private ActivityResultLauncher<Intent> fileChooserLauncher;
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.swipeRefreshLayout), (v, insets) -> {
int top = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top;
int bottom = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
int left = insets.getInsets(WindowInsetsCompat.Type.systemBars()).left;
int right = insets.getInsets(WindowInsetsCompat.Type.systemBars()).right;
v.setPadding(left, top, right, bottom);
return insets;
});
fileChooserLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
// Para selección de archivos de galería
if (file_path == null) {
return;
}
Uri[] uris = WebChromeClient.FileChooserParams.parseResult(result.getResultCode(), result.getData());
file_path.onReceiveValue(uris);
file_path = null;
});
mSwipeRefreshLayout = findViewById(R.id.swipeRefreshLayout);
mSwipeRefreshLayout.setOnChildScrollUpCallback(new SwipeRefreshLayout.OnChildScrollUpCallback() {
@Override
public boolean canChildScrollUp(@NonNull SwipeRefreshLayout parent, @Nullable View child) {
return mWebView.canScrollVertically(-1);
}
});
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mWebView.reload();
}
});
mWebView = (TouchyWebView) findViewById(R.id.webView);
// mWebView.setWebViewClient( mCesaWebViewClient);
mWebView.addJavascriptInterface(new JavaScriptShareInterface(), "AndroidShareHandler");
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setAllowFileAccess(true);
webSettings.setAllowContentAccess(true);
webSettings.setAllowFileAccessFromFileURLs(true);
webSettings.setAllowUniversalAccessFromFileURLs(true);
webSettings.setDomStorageEnabled(true);
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
webSettings.setDatabaseEnabled(false);
webSettings.setDisplayZoomControls(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setMediaPlaybackRequiresUserGesture(false);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
Log.e("WebView", "Error loading URL: " + failingUrl + " - " + description + " (Code: " + errorCode + ")");
// Intentar recargar una vez más después de un error
if (failingUrl.equals(_URL)) {
Log.d("WebView", "Attempting to reload after error...");
new android.os.Handler().postDelayed(new Runnable() {
@Override
public void run() {
view.reload();
}
}, 2000); // Esperar 2 segundos antes de reintentar
}
}
@Override
public void onReceivedSslError(WebView view, android.webkit.SslErrorHandler handler, android.net.http.SslError error) {
Log.e("WebView", "SSL Error: " + error.toString() + " for URL: " + error.getUrl());
// Continuar a pesar del error SSL (solo para desarrollo/testing)
handler.proceed();
}
@Override
public void onPageStarted(WebView view, String url, android.graphics.Bitmap favicon) {
super.onPageStarted(view, url, favicon);
Log.d("WebView", "Started loading: " + url);
mSwipeRefreshLayout.setRefreshing(true);
}
@Override
public void onPageFinished(WebView view, String url) {
findViewById(R.id.webView).setVisibility(View.VISIBLE);
mSwipeRefreshLayout.setRefreshing(false);
Log.d("WebView", "Finished loading: " + url);
}
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
if(url.contains("leaderslinked.com") ) return false;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
MainActivity.this.startActivity(intent);
return true;
}
});
mWebView.setWebChromeClient(new WebChromeClient()
{
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if(file_permission()) {
file_path = filePathCallback;
// Solo permitir selección de galería/archivos
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType(file_type);
contentSelectionIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Seleccionar archivo");
fileChooserLauncher.launch(chooserIntent);
return true;
} else {
return false;
}
}
});
// Verify network connection
if (isNetworkAvailable()) {
Log.d("WebView", "Network available, proceeding to load URL");
// Clear cache before load
clearWebViewCache();
mWebView.loadUrl(_URL);
} else {
Log.e("WebView", "No network connection available");
}
}
private void clearWebViewCache() {
// Limpiar todos los tipos de caché del WebView
mWebView.clearCache(true);
mWebView.clearFormData();
mWebView.clearHistory();
mWebView.clearSslPreferences();
// Clear cookies
android.webkit.CookieManager.getInstance().removeAllCookies(null);
android.webkit.CookieManager.getInstance().flush();
Log.d("WebView", "Cache, cookies and data cleared completely");
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager =
(ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
boolean isConnected = activeNetworkInfo != null && activeNetworkInfo.isConnected();
Log.d("WebView", "Network status: " + (isConnected ? "Connected" : "Disconnected"));
return isConnected;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && this.mWebView.canGoBack()) {
this.mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
protected void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
// Save the state of the WebView
mWebView.saveState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
// Restore the state of the WebView
mWebView.restoreState(savedInstanceState);
}
@Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
}
public boolean file_permission(){
int checkPermissionExternal = PackageManager.PERMISSION_GRANTED;
int checkPermissionReadMediaAudio = PackageManager.PERMISSION_GRANTED;
int checkPermissionReadMediaVideo = PackageManager.PERMISSION_GRANTED;
int checkPermissionReadMediaImages = PackageManager.PERMISSION_GRANTED;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
checkPermissionExternal = ContextCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE);
} else {
checkPermissionReadMediaAudio = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_AUDIO);
checkPermissionReadMediaVideo = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_VIDEO);
checkPermissionReadMediaImages = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES);
}
boolean ok = true;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
ok = checkPermissionExternal == PackageManager.PERMISSION_GRANTED;
} else {
ok = checkPermissionReadMediaAudio == PackageManager.PERMISSION_GRANTED;
ok = ok && checkPermissionReadMediaVideo == PackageManager.PERMISSION_GRANTED;
ok = ok && checkPermissionReadMediaImages == PackageManager.PERMISSION_GRANTED;
}
if(!ok) {
ArrayList<String> newPermissionList = new ArrayList<>();
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
if(checkPermissionExternal != PackageManager.PERMISSION_GRANTED) {
newPermissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
} else {
if(checkPermissionReadMediaAudio != PackageManager.PERMISSION_GRANTED) {
newPermissionList.add(Manifest.permission.READ_MEDIA_AUDIO);
}
if(checkPermissionReadMediaVideo != PackageManager.PERMISSION_GRANTED) {
newPermissionList.add(Manifest.permission.READ_MEDIA_VIDEO);
}
if(checkPermissionReadMediaImages != PackageManager.PERMISSION_GRANTED) {
newPermissionList.add(Manifest.permission.READ_MEDIA_IMAGES);
}
}
String permissions[] = newPermissionList.toArray(new String[newPermissionList.size()]);
ActivityCompat.requestPermissions(MainActivity.this, permissions, 1);
return false; // No abrir selector hasta que se concedan permisos
} else {
return true; // Permisos concedidos, permitir abrir selector
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
boolean allPermissionsGranted = true;
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
allPermissionsGranted = false;
break;
}
}
if (allPermissionsGranted) {
Log.d("MainActivity", "Todos los permisos han sido concedidos");
// Los permisos han sido concedidos, el usuario puede intentar nuevamente abrir el selector
} else {
Log.d("MainActivity", "Algunos permisos fueron denegados");
// Algunos permisos fueron denegados
}
}
}
private class JavaScriptShareInterface {
@JavascriptInterface
public void share(String url, String title, String content) {
try {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_SUBJECT, title);
String shareMessage= "\n" + content + "\n\n";
shareMessage = shareMessage + url +"\n\n";
shareIntent.putExtra(Intent.EXTRA_TEXT, shareMessage);
Intent chooserIntent = Intent.createChooser(shareIntent, "choose one");
startActivity(chooserIntent);
} catch(Exception e) {
//e.toString();
}
}
}
}