2010-03-05 12 views
10

J'ai actuellement un problème avec la géolocalisation dans un webview. J'ai une webapp. Je n'utilise actuellement ni phonegap ni aucun autre framework mobile. Je n'ai pas réussi à obtenir l'API apk html5 géolocalisation intégrée pour travailler sur une application qui fonctionne dans une vue Web dans une application Android. Le site fonctionne très bien à partir du navigateur chrome sur android 2.0+ (géolocalisation supportée).Android: Utiliser html5 pour déterminer la géolocalisation dans webview avec javascript api

Je compile contre la version android api 5.

J'ai lu this post déjà

solution de Phonegap d'écrire un proxy qui encapsule le construit en appel et utilise l'activité d'accueil est plutôt bon, mais je préférerais utiliser le built-in à la webview (webkit) sans utiliser le vide téléphonique.

J'ai mis les autorisations appropriées dans le fichier manifeste:

<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.ACCESS_GPS" /> 
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" /> 
<uses-permission android:name="android.permission.ACCESS_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 

Voici un exemple extrait de code:

webview = (WebView) findViewById(R.id.webview); 
pbarDialog = new ProgressDialog(this); 
pbarDialog.setCancelable(false); 
pbarDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 
webview.setWebViewClient(new MyWebViewClient()); 
webview.getSettings().setJavaScriptEnabled(true); 
webview.setWebChromeClient(new MyChromeWebViewClient()); 
webview.setVerticalScrollBarEnabled(false); 
WebSettings webSettings = webview.getSettings(); 
webSettings.setSavePassword(true); 
webSettings.setSaveFormData(true); 
webSettings.setJavaScriptEnabled(true); 
webSettings.setSupportZoom(false); 
webSettings.setJavaScriptCanOpenWindowsAutomatically(true); 
webSettings.setGeolocationEnabled(true); 

...

private class MyChromeWebViewClient extends WebChromeClient { 

@Override 
public void onProgressChanged(WebView view, int progress) { 
    // Activities and WebViews measure progress with different scales. 
    // The progress meter will automatically disappear when we reach 100% 
    activity.setProgress(progress * 100); 
} 

@Override 
public boolean onJsAlert(WebView view, String url, String message, JsResult result) { 
    Log.d(LOG_TAG, message); 
    // This shows the dialog box. This can be commented out for dev 
    AlertDialog.Builder alertBldr = new AlertDialog.Builder(activity); 
    alertBldr.setMessage(message); 
    alertBldr.setTitle("Alert"); 
    alertBldr.show(); 
    result.confirm(); 
    return true; 
    } 

} 

private class MyWebViewClient extends WebViewClient { 

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

@Override 
public void onReceivedError(WebView view, int errorCode, 
    String description, String failingUrl) { 
    } 
} 

Quelqu'un at-il d'autre eu des problèmes avec l'obtention d'une application web pour travailler dans le webview?

+0

avez-vous des exemples de html/javascript que vous utilisez. Comme cela devrait fonctionner .... Il suffit de noter que Chrome vient juste d'avoir la géolocalisation dans le canal de développement. – Kinlan

+0

Y a-t-il une solution mise à jour à ce problème? –

Répondre

8

Ajouter onGeolocationPermissionsShowPrompt() à MyChromeWebViewClient comme ci-dessous:

private class MyChromeWebViewClient extends WebChromeClient { 

    @Override 
    public void onProgressChanged(WebView view, int progress) { 
     // Activities and WebViews measure progress with different scales. 
     // The progress meter will automatically disappear when we reach 100% 
     activity.setProgress(progress * 100); 
    } 

    @Override 
    public boolean onJsAlert(WebView view, String url, String message, JsResult result) { 
     Log.d(LOG_TAG, message); 
     // This shows the dialog box. This can be commented out for dev 
     AlertDialog.Builder alertBldr = new AlertDialog.Builder(activity); 
     alertBldr.setMessage(message); 
     alertBldr.setTitle("Alert"); 
     alertBldr.show(); 
     result.confirm(); 
     return true; 
    } 

    public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { 
     callback.invoke(origin, true, false); 
    } 
} 

Vous devez importer "android.webkit.GeolocationPermissions".

Ajouter cette autorisation:

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

Cela fonctionne, je suppose.

+0

Merci, il me manquait cette fonction 'WebChromeClient'! – AAlferez

1

Votre problème peut être le même problème avec Android WebView using Geolocation.
Je pense que HTML5 utiliser la base de données locale, vous devez donc ajouter quelques exigences HTML5 comme celui-ci

// HTML5 API flags 
webView.getSettings().setAppCacheEnabled(true); 
webView.getSettings().setDatabaseEnabled(true); 
webView.getSettings().setDomStorageEnabled(true); 
0

Vous avez essayé cette classe html5webview.

private HTML5WebView mWebView; 
String url = "SOMEURL"; 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    mWebView = new HTML5WebView(this); 
    if (savedInstanceState != null) { 
     mWebView.restoreState(savedInstanceState); 
    } else { 
     mWebView.loadUrl(url); 
    } 
    setContentView(mWebView.getLayout()); 
} 
@Override 
public void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    mWebView.saveState(outState); 
} 
0

Partage ma classe d'activité de travail, c'est une solution complète qui peut démontrer

  • Affichage de dialogue de chargement alors que la page Web chargement
  • Demandez la permission à la guimauve et au-dessus
  • Poignée erreur de page Web
  • vérifier la connexion Internet et ouvrir la page de paramétrage
  • Han mani- autorisation de géolocalisation avec et sans dialogue

Espoir il sauver le temps de quelqu'un

 /** 
    * Created by Hitesh.Sahu on 3/24/2017. 
    */ 

    public class WebViewActivity extends AppCompatActivity { 

     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; 
     private WebView webView; 


     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_webview); 
      webView = (WebView) findViewById(R.id.webView); 
      rootView = (CoordinatorLayout) findViewById(R.id.root_view); 

      if (Build.VERSION.SDK_INT >= 23) { 
       // Marshmallow+ Permission APIs 
       fuckMarshMallow(); 
      } 

      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 
       if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)) { 
        WebView.setWebContentsDebuggingEnabled(true); 
       } 
      } 
      webView.setInitialScale(1); 
      webView.getSettings().setLoadWithOverviewMode(true); 
      webView.getSettings().setUseWideViewPort(true); 
      webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY); 
      webView.setScrollbarFadingEnabled(false); 

      webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); 
      webView.getSettings().setBuiltInZoomControls(true); 
      webView.setWebViewClient(new GeoWebViewClient()); 
      // Below required for geolocation 
      webView.getSettings().setJavaScriptEnabled(true); 
      webView.getSettings().setGeolocationEnabled(true); 
      webView.setWebChromeClient(new GeoWebChromeClient()); 

      webView.getSettings().setAppCacheEnabled(true); 
      webView.getSettings().setDatabaseEnabled(true); 
      webView.getSettings().setDomStorageEnabled(true); 

      webView.getSettings().setGeolocationDatabasePath(getFilesDir().getPath()); 

      webView.loadUrl("file:///android_asset/index.html"); 
     } 

     /** 
     * 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) { 
       // Always grant permission since the app itself requires location 
       // permission and the user has therefore already granted it 
       callback.invoke(origin, true, false); 

    //   final boolean remember = false; 
    //   AlertDialog.Builder builder = new AlertDialog.Builder(WebViewActivity.this); 
    //   builder.setTitle("Locations"); 
    //   builder.setMessage("Would like to use your Current Location ") 
    //     .setCancelable(true).setPositiveButton("Allow", new DialogInterface.OnClickListener() { 
    //    public void onClick(DialogInterface dialog, int id) { 
    //     // origin, allow, remember 
    //     callback.invoke(origin, true, remember); 
    //    } 
    //   }).setNegativeButton("Don't Allow", new DialogInterface.OnClickListener() { 
    //    public void onClick(DialogInterface dialog, int id) { 
    //     // origin, allow, remember 
    //     callback.invoke(origin, false, remember); 
    //    } 
    //   }); 
    //   AlertDialog alert = builder.create(); 
    //   alert.show(); 
      } 
     } 

     /** 
     * 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(WebViewActivity.this); 

      @Override 
      public void onPageStarted(WebView view, String url, Bitmap favicon) { 
       super.onPageStarted(view, url, favicon); 
       webViewPreviousState = PAGE_STARTED; 

       if (loadingDialog == null || !loadingDialog.isShowing()) 
        loadingDialog = ProgressDialog.show(WebViewActivity.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(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(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED 


          ) { 
         // All Permissions Granted 

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

        } else { 
         // Permission Denied 
         Toast.makeText(WebViewActivity.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, 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(WebViewActivity.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(WebViewActivity.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; 
     } 
    }