如何解决针对跨应用脚本编写的 WebView URL 接收实践
没错,我的应用也因跨应用脚本而被 Google 删除。问题的一半可能是问题出在哪里,但我更关心的是“现代应用程序中接收菜单项的最佳实践是什么(包含传递给 webview 的 ListTile 和图块 URL 的标题的对象)”。
我的应用目前有一个 2 列的卡片回收站视图。应用程序从 Google Firestore 接收所有文档,将它们转换为对象并在 recyclerview 中显示它们。一旦用户点击其中一张卡片,webview 就会打开,其中包含菜单中卡片中提供的 url。
自从 google 删除了我的应用程序后,我尝试禁用 javascript,但我明白它对于禁用 webviews 来说太重要了,所以我保持启用状态。我在清单中将每个活动更改为“exported=false”,并添加了一个用于安全 webview 的元标记,但所有这些都没有完成谷歌接受它的工作,所以我想知道是否要在应用程序中对 firebase 信息进行硬编码,但是会弄乱应用程序的主要思想,这很容易从任何地方和任何人进行管理,而无需 IT 人员对应用程序进行硬编码。 附注我知道谷歌将我的 firestore-info-to-webviews 关系视为一个巨大的安全漏洞,因此我不知道现在该怎么做才能让我的应用重新收费。
这里有一些代码来看看我得到的东西:
在我跳入代码之前,这是我按下菜单中的卡片/项目之一时的样子 - 网页视图打开并加载卡片提供的网址:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="viaapp_v2">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true" />
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme.ViaTheme"
android:usesCleartextTraffic="true">
<activity
android:name=".systems.webview_activity.webview_base"
android:configChanges="orientation|screenSize"
android:parentActivityName=".main_screen.MenuScreen"
android:label="@string/title_webview">
<Meta-data android:name="android.webkit.WebView.EnableSafebrowsing"
android:value="true" />
<intent-filter>
<category android:name="android.intent.category.broWSABLE" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="file" />
<data android:mimeType="\*/\*" />
<data android:pathPattern=".*\\.kdb" />
<data android:host="*" />
</intent-filter>
</activity>
<activity
android:name="viaapp_v2.main_screen.MenuScreen"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTask"
android:label="@string/title_activity_menu_screen" />
</application>
</manifest>
2nd - 菜单项对象类:
public class MenuObject {
String title;
String icon_url;
String webURL;
String activity;
int bgcolor;
//constructor to lead to webview activity
public MenuObject(String title,String icon_url,String webURL,String activity) {
this.title = title;
this.icon_url = icon_url;
this.webURL = webURL;
this. activity = activity;
Log.i("MenuObject","Object "+title+" created");
}
//constructor to lead to lecture graph
public MenuObject(String title,String activity) {
this.title = title;
this.icon_url = icon_url;
this. activity = activity;
Log.i("MenuObject","Object "+title+" created");
}
//WITH BACKGROUND COLOR
//constructor to lead to webview activity
public MenuObject(String title,String activity,int bgcolor) {
this.title = title;
this.icon_url = icon_url;
this.webURL = webURL;
this. activity = activity;
this.bgcolor = bgcolor;
Log.i("MenuObject","Object "+title+" created with bgcolor "+bgcolor);
}
//constructor to lead to lecture graph
public MenuObject(String title,int bgcolor) {
this.title = title;
this.icon_url = icon_url;
this. activity = activity;
this.bgcolor = bgcolor;
Log.i("MenuObject","Object "+title+" created with bgcolor "+bgcolor);
}
public String getActivity() {
return activity;
}
public String getTitle() {
return title;
}
public String getIcon_url() {
return icon_url;
}
public String getWebURL() {
return webURL;
}
public int getColor() {
return bgcolor;
}
}
最后一个,webview 基础:
public class webview_base extends AppCompatActivity {
String url;
WebView webview_Box;
View root;
private static final String TAG = webview_base.class.getSimpleName();
private ValueCallback<Uri[]> mUploadMessage;
private FloatingActionButton leave_page,webview_goBack,webview_goForward;
private final static int FILECHOOSER_RESULTCODE = 1;
@Override
protected void onRestart() {
super.onRestart();
}
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview_base);
root = getwindow().getDecorView().getRootView();
leave_page = findViewById(R.id.leave_webview);
leave_page.setonClickListener(new View.OnClickListener() {
public void onClick(View v) {
returnToMenu();
}
});
webview_Box = findViewById(R.id.webview_Box);
WebSettings webSettings = webview_Box.getSettings();
// webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
webSettings.setJavaScriptEnabled(true);
// webSettings.setAllowFileAccess(true);
// webSettings.setSupportMultipleWindows(true);
// webSettings.setAllowContentAccess(true);
// webSettings.setDatabaseEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setAppCacheEnabled(false);
webSettings.setSavePassword(true);
webSettings.setSaveFormData(true);
webSettings.setAppCacheMaxSize(0);
webSettings.setAllowFileAccess(false);
webSettings.setAppCacheEnabled(false);
// webSettings.setUseWideViewPort(true);
// webSettings.setLoadWithOverviewmode(true);
// webSettings.setDatabasePath("/data/data/" + getPackageName() + "/databases/");
webview_Box.setWebChromeClient(new MyChromeClient());
webview_Box.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url,String userAgent,String contentdisposition,String mimeType,long contentLength) {
//if they are granted
if(hasstoragePermissions(webview_base.this)){
//if perms are granted,starts file download
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setMimeType(mimeType);
String cookies = CookieManager.getInstance().getCookie(url);
request.addRequestHeader("cookie",cookies);
request.addRequestHeader("User-Agent",userAgent);
request.setDescription(getString(R.string.downloading_file));
request.setTitle(URLUtil.guessFileName(url,contentdisposition,mimeType));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,URLUtil.guessFileName(url,mimeType));
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);
//make toast notifying for dile download
Toast.makeText(getApplicationContext(),getString(R.string.downloading_file),Toast.LENGTH_LONG).show();
}
}
});
CookieManager.getInstance().acceptCookie();
//if SDK version is greater of 19 then activate hardware acceleration otherwise activate software acceleration
if (Build.VERSION.SDK_INT >= 19) {
webview_Box.setLayerType(View.LAYER_TYPE_HARDWARE,null);
} else {
webview_Box.setLayerType(View.LAYER_TYPE_SOFTWARE,null);
}
if (savedInstanceState == null) {
Bundle extras = getIntent().getExtras();
if(extras == null) {
//close webview doe to error
Log.e("WEBVIEW_BASE","No URL passed in extras");
returnToMenu();
} else {
//open notification url
if(extras.getString("web_url") != null) url = extras.getString("web_url");
//otherwise open menu provided url
else url = extras.getString("link");
}
} else {
url = (String) savedInstanceState.getSerializable("link");
}
webview_Box.setWebViewClient(new WebViewClient() {
@Override public void onReceivedSslError(WebView v,final SslErrorHandler handler,SslError er){
new AlertDialog.Builder(webview_base.this)
.setTitle(getString(R.string.warning))
.setMessage(getString(R.string.insecure_source))
//if user clicks to proceed to site
.setPositiveButton(getString(R.string.proceed),new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
handler.proceed();
}
})
//if user clicks to leave the site loading process
.setNegativeButton(getString(R.string.terminate_page_load),new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,int which) {
webview_Box.goBack();
}
})
.setIcon(R.drawable.via)
.show();
}
@Override
public void onReceivedError(WebView view,WebResourceRequest request,WebResourceError error){
show_web_error();
Log.e("Web loading error",error.toString());
}
//Show loader on url load
public void onPageStarted(WebView view,String url,Bitmap favicon) {
enable_web_loading_screen();
}
// Called when all page resources loaded
public void onPageFinished(WebView view,String url) {
//hides splashscreen with animation
hide_web_loading_screen();
}
@Override
public boolean shouldOverrideUrlLoading(WebView view,String url) {
// If url contains mailto link then open Mail Intent
if (url.contains("tel:") || url.contains("sms:") || url.contains("smsto:") || url.contains("mailto:") || url.contains("mms:") || url.contains("mmsto:")) {
// Could be cLeverer and use a regex
//Open links in new browser
view.getContext().startActivity(
new Intent(Intent.ACTION_VIEW,Uri.parse(url)));
} else {
// Stay within this webview and load url
webview_Box.loadUrl(url);
}
return true;
}
});
//laods passed URL from notification,load overwritten url
webview_Box.loadUrl(url);
//goBack FAB listener
webview_goBack = findViewById(R.id.webview_goBack);
webview_goBack.setonClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(webview_Box.canGoBack())webview_Box.goBack();
}
});
//goForward FAB listener
webview_goForward = findViewById(R.id.webview_goForward);
webview_goForward.setonClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(webview_Box.canGoForward())webview_Box.goForward();
}
});
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig){
super.onConfigurationChanged(newConfig);
}
@Override
public void onActivityResult(int requestCode,int resultCode,Intent data) {
super.onActivityResult(requestCode,resultCode,data);
if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == mUploadMessage || data == null || resultCode != RESULT_OK) {
return;
}
Uri[] result = null;
String dataString = data.getDataString();
if (dataString != null) {
result = new Uri[]{Uri.parse(dataString)};
}
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
@Override
public void onRequestPermissionsResult(int requestCode,@NonNull String[] permissions,@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode,permissions,grantResults);
int i = 0;
boolean is_good = true;
for(String permission : permissions){
//check if any of permissions were declined
if(grantResults[i] == PackageManager.PERMISSION_DENIED){
//notify for any ungranted perms
is_good = false;
break;
}
i++;
}
if(!is_good){
Snackbar.make(root,R.string.ungranted_perms,Snackbar.LENGTH_LONG).show();
}else {
Snackbar.make(root,R.string.granted_perms,Snackbar.LENGTH_LONG).show();
}
}
public static boolean hasstoragePermissions(Activity activity) {
// Check if we have read or write permissions for download/uplaod options
int writePermission = ActivityCompat.checkSelfPermission(activity,Manifest.permission.WRITE_EXTERNAL_STORAGE);
int readPermission = ActivityCompat.checkSelfPermission(activity,Manifest.permission.READ_EXTERNAL_STORAGE);
boolean result = true;
//if permission is not granted
if(writePermission != PackageManager.PERMISSION_GRANTED || readPermission != PackageManager.PERMISSION_GRANTED){
//request permission
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE},101);
//recheck permission
if(ActivityCompat.checkSelfPermission(activity,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(activity,Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) result = false;
}
//return permission status
return result;
}
public class MyChromeClient extends WebChromeClient {
@Override
public boolean onShowFileChooser(WebView webView,ValueCallback<Uri[]> filePathCallback,FileChooserParams fileChooserParams) {
// asegurar que no existan callbacks
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(null);
}
mUploadMessage = filePathCallback;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*"); // set MIME type to filter
webview_base.this.startActivityForResult(Intent.createChooser(i,"File Chooser"),webview_base.FILECHOOSER_RESULTCODE );
return true;
}
}
public boolean onKeyDown(int keyCode,KeyEvent event) {
// Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && webview_Box.canGoBack()) {
webview_Box.goBack();
return true;
}
// If it wasn't the Back key or there's no web page history,bubble up to the default
// system behavior (probably exit the activity)
return super.onKeyDown(keyCode,event);
}
@Override
public void onBackpressed() {
if (webview_Box.canGoBack()) {
webview_Box.goBack();
} else {
returnToMenu();
}
}
private void GoForward() {
if (webview_Box.canGoForward()) {
webview_Box.goForward();
}
}
private void enable_web_loading_screen(){
Log.d("Web loading","started");
//opens splashscreen
root.findViewById(R.id.via_splash_screen_3).setVisibility(View.VISIBLE);
root.findViewById(R.id.splash_screen_progress_3).setVisibility(View.VISIBLE);
}
private void hide_web_loading_screen(){
Log.d("Web loading","finished");
//hides splashscreen with animation
root.findViewById(R.id.via_splash_screen_3).setAnimation(AnimationUtils.loadAnimation(webview_base.this,R.anim.disappear));
root.findViewById(R.id.via_splash_screen_3).setVisibility(View.GONE);
root.findViewById(R.id.splash_screen_progress_3).setVisibility(View.GONE);
}
private void show_web_error() {
//if any other error occurs
Snackbar.make(findViewById(R.id.web_base_view),getText(R.string.web_error_text),Snackbar.LENGTH_INDEFINITE)
.setAction(getString(R.string.reload_page),new View.OnClickListener() {
@Override
public void onClick(View view) {
WebView web = findViewById(R.id.webview_Box);
web.loadUrl(url);
enable_web_loading_screen();
}
})
.setActionTextColor(getResources().getColor(android.R.color.holo_red_light ))
.show();
}
public void returnToMenu(){
finish();
//brings to top or opens a new home activity
startActivity(new Intent(webview_base.this,MenuScreen.class));
}
}
很高兴在这里听到您对我的问题的意见。 干杯。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。