Android Webview:navigator.geolocation API不起作用,引发异常POSITION_UNAVAILABLE

用户名

我正在尝试将网络应用程序嵌入Android Webview。我的Web应用程序使用HTML5 Geolocation API来获取用户的当前位置。现在,我们正在尝试创建一个可在Webview中打开它的android应用,用户也可以从移动应用中执行相同的操作。在Webview中,我们看不到用户要求允许或拒绝的任何类型的消息,就像在浏览器中看到的那样,它会引发错误POSITION_UNAVAILABLE

与地理位置API相关的Web应用程序JS代码

// Geolocation fetch function for getting value 
function fetchGeoLocationFunction(result){
    if(result ==  true){
        // reset the search location to initiate with the new process
        resetAddressSelection();
        if (navigator.geolocation){            
            navigator.geolocation.getCurrentPosition(showPosition,showError);
        }
        else {
            var msgToDisplay = 'Geolocation is not supported by your browser or device, Please try with any latest popular browser';
            CreatePopupMessage(false,msgToDisplay,'Not Supported',false);            
        }
    }
}

function showPosition(position){   
    var attempt = 1;
    convertGeoCordstoAddress(position.coords.latitude,position.coords.longitude,attempt);
}

function showError(error){
showProcessingBar(); // Show the Processing Bar
setTimeout(function(){
   hideProcessingBar();
   console.log('Its in failure',error.code);
   var err_Msg = '';
   switch(error.code){    
        case error.PERMISSION_DENIED:
          err_Msg = 'You have denied the Request for your Geo location, without that You can\'t proceed further. Please allow this operation from your browser settings'
          break;
        case error.POSITION_UNAVAILABLE:
          err_Msg ='Location information is unavailable. please try after some time'
          break;
        case error.TIMEOUT:
          err_Msg ='The request to get user location timed out.Please try again'
          break;
        case error.UNKNOWN_ERROR:
          err_Msg ='An unknown error occurred. if the error is repetative, please contact to application provider'
          break;
   }   
   if(err_Msg == ''){
       err_Msg  = 'An Error Occured, Contact to Application provider';
   }
   //alert(err_Msg);
   CreatePopupMessage(false,err_Msg,'',true);   
},500);  
}

这是我的Android应用程序代码开始

Android应用程式程式码

MainActivuty.java

package com.example.timedin;

import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;

import android.provider.Settings;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.CookieManager;
import android.webkit.GeolocationPermissions;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.Manifest;

public class MainActivity extends AppCompatActivity {
    private WebView webView;
    final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
    private int webViewPreviousState;
    private final int PAGE_STARTED = 0x1;
    private final int PAGE_REDIRECTED = 0x2;
    private CoordinatorLayout rootView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // webview initilization
        webView = (WebView) findViewById(R.id.webview);
        webView.setWebViewClient(new GeoWebViewClient());
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setAppCacheEnabled(false);
        webView.getSettings().setDatabaseEnabled(true);
        webView.getSettings().setDomStorageEnabled(true);
        webView.getSettings().setGeolocationEnabled(true);

        /// Below required for geolocation
        webView.setWebChromeClient(new GeoWebChromeClient());
        webView.getSettings().setGeolocationDatabasePath(getFilesDir().getPath());
        webView.loadUrl("<my_webapp_url>");

    }

    /**
     * WebChromeClient subclass handles UI-related calls
     * Note: think chrome as in decoration, not the Chrome browser
     */
    public class GeoWebChromeClient extends android.webkit.WebChromeClient {
        @Override
        public void onGeolocationPermissionsShowPrompt(final String origin,
                                                       final GeolocationPermissions.Callback callback) {

            // permission and the user has therefore already granted it
            callback.invoke(origin, true, false);

        }
    }

    /**
     * WebViewClient subclass loads all hyperlinks in the existing WebView
     */
    public class GeoWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            // When user clicks a hyperlink, load in the existing WebView
            view.loadUrl(url);
            return true;
        }

        Dialog loadingDialog = new Dialog(MainActivity.this);

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            webViewPreviousState = PAGE_STARTED;
            //CookieManager.getInstance().removeAllCookies(null);
            if (loadingDialog == null || !loadingDialog.isShowing())
                loadingDialog = ProgressDialog.show(MainActivity.this, "",
                        "Loading Please Wait", true, true,
                        new DialogInterface.OnCancelListener() {

                            @Override
                            public void onCancel(DialogInterface dialog) {
                                // do something
                            }
                        });

            loadingDialog.setCancelable(false);
        }


        @RequiresApi(api = Build.VERSION_CODES.M)
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request,
                                    WebResourceError error) {


            if (isConnected()) {
                final Snackbar snackBar = Snackbar.make(rootView, "onReceivedError : " + error.getDescription(), Snackbar.LENGTH_INDEFINITE);
                snackBar.setAction("Reload", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        webView.loadUrl("javascript:window.location.reload( true )");
                    }
                });
                snackBar.show();
            } else {
                final Snackbar snackBar = Snackbar.make(rootView, "No Internet Connection ", Snackbar.LENGTH_INDEFINITE);
                snackBar.setAction("Enable Data", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        startActivityForResult(new Intent(Settings.ACTION_WIRELESS_SETTINGS), 0);
                        webView.loadUrl("javascript:window.location.reload( true )");
                        snackBar.dismiss();
                    }
                });
                snackBar.show();
            }

            super.onReceivedError(view, request, error);

        }

        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void onReceivedHttpError(WebView view,
                                        WebResourceRequest request, WebResourceResponse errorResponse) {

            if (isConnected()) {
                final Snackbar snackBar = Snackbar.make(rootView, "HttpError : " + errorResponse.getReasonPhrase(), Snackbar.LENGTH_INDEFINITE);

                snackBar.setAction("Reload", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        webView.loadUrl("javascript:window.location.reload( true )");
                    }
                });
                snackBar.show();
            } else {
                final Snackbar snackBar = Snackbar.make(rootView, "No Internet Connection ", Snackbar.LENGTH_INDEFINITE);
                snackBar.setAction("Enable Data", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        startActivityForResult(new Intent(Settings.ACTION_WIRELESS_SETTINGS), 0);
                        webView.loadUrl("javascript:window.location.reload( true )");
                        snackBar.dismiss();
                    }
                });
                snackBar.show();
            }
            super.onReceivedHttpError(view, request, errorResponse);
        }

        @Override
        public void onPageFinished(WebView view, String url) {

            if (webViewPreviousState == PAGE_STARTED) {

                if (null != loadingDialog) {
                    loadingDialog.dismiss();
                    loadingDialog = null;
                }
            }
        }
    }


    /**
     * Check if there is any connectivity
     *
     * @return is Device Connected
     */
    public boolean isConnected() {

        ConnectivityManager cm = (ConnectivityManager)
                this.getSystemService(Context.CONNECTIVITY_SERVICE);

        if (null != cm) {
            NetworkInfo info = cm.getActiveNetworkInfo();
            return (info != null && info.isConnected());
        }

        return false;

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: {
                Map<String, Integer> perms = new HashMap<String, Integer>();
                // Initial
                perms.put(android.Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);


                // Fill with results
                for (int i = 0; i < permissions.length; i++)
                    perms.put(permissions[i], grantResults[i]);

                // Check for ACCESS_FINE_LOCATION
                if (perms.get(android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED


                ) {
                    // All Permissions Granted

                    // Permission Denied
                    Toast.makeText(MainActivity.this, "All Permission GRANTED !! Thank You :)", Toast.LENGTH_SHORT)
                            .show();

                } else {
                    // Permission Denied
                    Toast.makeText(MainActivity.this, "One or More Permissions are DENIED Exiting App :(", Toast.LENGTH_SHORT)
                            .show();

                    finish();
                }
            }
            break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    private void fuckMarshMallow() {
        List<String> permissionsNeeded = new ArrayList<String>();

        final List<String> permissionsList = new ArrayList<String>();
        if (!addPermission(permissionsList, android.Manifest.permission.ACCESS_FINE_LOCATION))
            permissionsNeeded.add("Show Location");

        if (permissionsList.size() > 0) {
            if (permissionsNeeded.size() > 0) {

                // Need Rationale
                String message = "App need access to " + permissionsNeeded.get(0);

                for (int i = 1; i < permissionsNeeded.size(); i++)
                    message = message + ", " + permissionsNeeded.get(i);

                showMessageOKCancel(message,
                        new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                                        REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
                            }
                        });
                return;
            }
            requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                    REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
            return;
        }

        Toast.makeText(MainActivity.this, "No new Permission Required- Launching App .You are Awesome!!", Toast.LENGTH_SHORT)
                .show();
    }


    private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(MainActivity.this)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", null)
                .create()
                .show();
    }

    @TargetApi(Build.VERSION_CODES.M)
    private boolean addPermission(List<String> permissionsList, String permission) {

        if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
            permissionsList.add(permission);
            // Check for Rationale Option
            if (!shouldShowRequestPermissionRationale(permission))
                return false;
        }
        return true;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

因此,每当我在android Webview中运行该应用程序时,它都不会问任何问题,只是向我显示带有错误的弹出消息,POSITION_UNAVAILABLE即JS代码中的错误,从而导致错误Location information is unavailable. please try after some time

我尝试了其他代码逻辑,并阅读了其他各种答案,但没有一个起作用。我目前正在测试android pie版本,但也尝试了其他版本,因此无法正常工作。

阿里·阿扎兹·阿拉姆

让我们检查问题的调用权限代码。而且我不知道您为什么以这种方式调用许可,因为我们有许多可以轻松调用它的媒介。让我们使用易于使用的nabinbhandari / Android-Permissions

以这种方式调用:

@Override
protected void onCreate(Bundle savedInstanceState) {

                .....................


String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION, 
Manifest.permission.ACCESS_COARSE_LOCATION};
Permissions.check(this/*context*/, permissions, null/*rationale*/, null/*options*/, new 
PermissionHandler() {
  @Override
  public void onGranted() {
    // call your task

    // webview initilization
    webView = (WebView) findViewById(R.id.webview);
    webView.setWebViewClient(new GeoWebViewClient());
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setAppCacheEnabled(false);
    webView.getSettings().setDatabaseEnabled(true);
    webView.getSettings().setDomStorageEnabled(true);
    webView.getSettings().setGeolocationEnabled(true);

    /// Below required for geolocation
    webView.setWebChromeClient(new GeoWebChromeClient());
    webView.getSettings().setGeolocationDatabasePath(getFilesDir().getPath());
    webView.loadUrl("<my_webapp_url>");


  }

  @Override
  public void onDenied(Context context, ArrayList<String> deniedPermissions) {
      // permission denied, block the feature.
    Toast.makeText(this,"Permission denied",Toast.LENGTH_SHORT);
  }

});

或者根据您的需要实现这些权限覆盖功能。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

navigator.geolocation.getCurrentPosition / watchPosition在android 6.0中不起作用

navigator.geolocation.getCurrentPosition()永远不会在Android的WebView中返回

在Android Webview的navigator.geolocation.getCurrentPosition()中获取“位置信息不可用”错误

navigator.geolocation.getCurrentPosition在React Native中不起作用

navigator.permissions.query在android / ios webview中不起作用

Javascript Navigator.geolocation

Android Google Geolocation API返回403错误

navigator.geolocation.watchPosition 空位

navigator.share在WebView中不起作用

样式在android webview中不起作用

Ajax在Android Webview中不起作用

相机允许不起作用android webview

android webview:网站控件不起作用

Geolocation.GetLocationAsync 不起作用

Chrome navigator.geolocation.getCurrentPosition()错误403

在Ionic中使用navigator.geolocation或$ cordovaGeolocation

navigator.geolocation.getCurrentPosition无法正常工作

如何强制 navigator.geolocation.getCurrentPosition 失败

Phonegap Android Geolocation watchPosition超时

MapsEngine + GeoLocation Javascript API

如何在Flutter的Webview中使用GeoLocation

用于WebView的android中的BasicAuthentication不起作用

window.close()在android webview中不起作用?

为什么minHeight属性在WebView Android中不起作用?

检查 webview 中的 url 更改 android 不起作用

JavaScript警报在Android WebView中不起作用

WebView.loadUrl(URL,headers)在android中不起作用

Android Webview Javascript-对脚本的引用不起作用

音频控件在 Android WebView 中不起作用