【问题标题】:How to ask user to enable GPS at the launch of application?如何在应用程序启动时要求用户启用 GPS?
【发布时间】:2018-08-10 17:17:03
【问题描述】:
private void turnGPSOn(){
String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);

if(!provider.contains("gps")){ //if gps is disabled
    final Intent poke = new Intent();
    poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider"); 
    poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
    poke.setData(Uri.parse("3")); 
    sendBroadcast(poke);
}
}

查看 Logcat

04/20 17:35:26: Launching app
$ adb push F:\AndroidProject\Picker\app\build\outputs\apk\app-debug.apk /data/local/tmp/picker.novasyslabs.com.picker
$ adb shell pm install -r "/data/local/tmp/picker.novasyslabs.com.picker"
    pkg: /data/local/tmp/picker.novasyslabs.com.picker
Success


$ adb shell am start -n "picker.novasyslabs.com.picker/picker.novasyslabs.com.picker.SlashScreen" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 22502 on device sony-d2302-ZH80065A89
W/ResourceType: Found multiple library tables, ignoring...
W/ResourceType: Found multiple library tables, ignoring...
W/ResourceType: Found multiple library tables, ignoring...
W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
I/art: Background partial concurrent mark sweep GC freed 151(19KB) AllocSpace objects, 0(0B) LOS objects, 39% free, 13MB/22MB, paused 5.156ms total 20.919ms
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: picker.novasyslabs.com.picker, PID: 22502
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{picker.novasyslabs.com.picker/picker.novasyslabs.com.picker.SlashScreen}: java.lang.ClassCastException: picker.novasyslabs.com.picker.SlashScreen cannot be cast to com.google.android.gms.common.api.GoogleApiClient$ConnectionCallbacks
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2442)
                      at android.app.ActivityThread.access$800(ActivityThread.java:156)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:211)
                      at android.app.ActivityThread.main(ActivityThread.java:5371)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:372)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:945)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:740)
                   Caused by: java.lang.ClassCastException: picker.novasyslabs.com.picker.SlashScreen cannot be cast to com.google.android.gms.common.api.GoogleApiClient$ConnectionCallbacks
                      at picker.novasyslabs.com.picker.SlashScreen.onCreate(SlashScreen.java:65)
                      at android.app.Activity.performCreate(Activity.java:5990)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2332)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2442) 
                      at android.app.ActivityThread.access$800(ActivityThread.java:156) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:211) 
                      at android.app.ActivityThread.main(ActivityThread.java:5371) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at java.lang.reflect.Method.invoke(Method.java:372) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:945) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:740) 
Application terminated.

我尝试了许多其他选项,例如包管理器、位置管理器等,但无法做到我想要的。 我希望在启动应用程序时提示用户启用 GPS。 我不希望用户进入设置。

我想要的 API 级别 >=19。

请帮我解决我的问题......... 谢谢

【问题讨论】:

  • 如果您愿意使用 Google Play 服务,SettingsApi 有一些选项可以提示用户启用位置。 This sample app 演示了该技术。否则,你想要的是不可能的。
  • 使用这个stackoverflow.com/questions/29801368/…>
  • 感谢这对我有用。非常感谢你。 :)

标签: android android-location android-gps


【解决方案1】:

如果您想要如下图所示的内容,请继续。

  1. 在您的应用程序中添加以下依赖项build.gradle

      implementation 'com.google.android.gms:play-services-location:16.0.0'
    
  2. 创建您想要的位置请求类型,我们需要 GPS 的高精度

      LocationRequest locationRequest = LocationRequest.create();
      locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
      LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                    .addLocationRequest(locationRequest);
    
  3. 现在我们需要检查 GPS 的当前状态。为此,我们必须使用LocationServices.getSettingsClient(getActivity()).checkLocationSettings(builder.build()) 这将返回一个需要异步处理的Task。在 RESOLUTION_REQUIRED 情况下,我们要求用户授予权限,这是我们向用户显示启用 GPS 的提示的地方。

    Task<LocationSettingsResponse> result =
                    LocationServices.getSettingsClient(getActivity()).checkLocationSettings(builder.build());
    
    
    
    result.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
                @Override
                public void onComplete(@NonNull Task<LocationSettingsResponse> task) {
                    try {
                        LocationSettingsResponse response = task.getResult(ApiException.class);
                        // All location settings are satisfied. The client can initialize location
                        // requests here.
                    } catch (ApiException exception) {
                        switch (exception.getStatusCode()) {
                            case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                                // Location settings are not satisfied. But could be fixed by showing the
                                // user a dialog.
                                try {
                                    // Cast to a resolvable exception.
                                    ResolvableApiException resolvable = (ResolvableApiException) exception;
                                    // Show the dialog by calling startResolutionForResult(),
                                    // and check the result in onActivityResult().
                                    resolvable.startResolutionForResult(
                                            getActivity(),
                                            LocationRequest.PRIORITY_HIGH_ACCURACY);
                                } catch (IntentSender.SendIntentException e) {
                                    // Ignore the error.
                                } catch (ClassCastException e) {
                                    // Ignore, should be an impossible error.
                                }
                                break;
                            case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                                // Location settings are not satisfied. However, we have no way to fix the
                                // settings so we won't show the dialog.
                                break;
                        }
                    }
                }
            });
    
  4. 现在我们已经要求用户打开 GPS,我们需要检查用户是否允许或忽略它。为此,覆盖 onActivityResult。请注意,如果您在片段中实现上述代码,结果将在封闭的 Activity 中收到。所以重写Activity类中的onActivityResult。

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case LocationRequest.PRIORITY_HIGH_ACCURACY:
            switch (resultCode) {
                case Activity.RESULT_OK:
                    // All required changes were successfully made
                    Log.i(TAG, "onActivityResult: GPS Enabled by user");
                    break;
                case Activity.RESULT_CANCELED:
                    // The user was asked to change settings, but chose not to
                    Log.i(TAG, "onActivityResult: User rejected GPS request");
                    break;
                default:
                    break;
            }
            break;
        } 
    }
    

From Android Documentation

【讨论】:

    【解决方案2】:

    这是@Ananth 答案的 kotlin 实现

    private fun showLocationPrompt() {
            val locationRequest = LocationRequest.create()
            locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
            val builder = LocationSettingsRequest.Builder().addLocationRequest(locationRequest)
    
            val result: Task<LocationSettingsResponse> = LocationServices.getSettingsClient(activity).checkLocationSettings(builder.build())
    
            result.addOnCompleteListener { task ->
                try {
                    val response = task.getResult(ApiException::class.java)
                    // All location settings are satisfied. The client can initialize location
                    // requests here.
                } catch (exception: ApiException) {
                    when (exception.statusCode) {
                        LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
                            try {
                                // Cast to a resolvable exception.
                                val resolvable: ResolvableApiException = exception as ResolvableApiException
                                // Show the dialog by calling startResolutionForResult(),
                                // and check the result in onActivityResult().
                                resolvable.startResolutionForResult(
                                    activity, LocationRequest.PRIORITY_HIGH_ACCURACY
                                )
                            } catch (e: IntentSender.SendIntentException) {
                                // Ignore the error.
                            } catch (e: ClassCastException) {
                                // Ignore, should be an impossible error.
                            }
                        }
                        LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                            // Location settings are not satisfied. But could be fixed by showing the
                            // user a dialog.
    
                            // Location settings are not satisfied. However, we have no way to fix the
                            // settings so we won't show the dialog.
                        }
                    }
                }
            }
        }
    
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            super.onActivityResult(requestCode, resultCode, data)
            when (requestCode) {
                LocationRequest.PRIORITY_HIGH_ACCURACY -> {
                    if (resultCode == Activity.RESULT_OK) {
                        Log.e("Status: ","On")
                    } else {
                        Log.e("Status: ","Off")
                    }
                }
            }
        }
    

    【讨论】:

      【解决方案3】:

      如果您不想强制用户进入设置页面启用 GPS,请使用 SettingsApi。 这里是如何使用 SettingsApi 的链接 SettingsApi

      【讨论】:

      • 这已被弃用。
      【解决方案4】:

      Image of GPS permission like Google Maps

      如果你想像上面的链接那样请求许可,你可以参考我的回答: https://stackoverflow.com/a/64757407/10618364

      代码是使用 GoogleApiSettingsClient API 编写的,而不是使用已弃用的 GoogleClientApiSettingsApi

      它还与 Android 11 兼容。;)

      【讨论】:

        【解决方案5】:
        public void showSettingAlert()
            {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
                alertDialog.setTitle("GPS setting!");
                alertDialog.setMessage("GPS is not enabled, Do you want to go to settings menu? ");
                alertDialog.setPositiveButton("Setting", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        context.startActivity(intent);
                    }
                });
                alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                });
                alertDialog.show();
            }
        

        【讨论】:

        • 问题是“我不希望用户进入设置。”
        • 不,最终决定取决于用户打开或关闭 GPS
        • 您提示此对话框,直到 GPS 开启
        猜你喜欢
        • 1970-01-01
        • 2012-05-12
        • 1970-01-01
        • 1970-01-01
        • 2011-03-07
        • 2019-06-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多