【问题标题】:How to turn on the GPS on Android如何在 Android 上打开 GPS
【发布时间】:2012-04-13 06:28:33
【问题描述】:

我正在开发一个需要激活 GPS 的安卓应用。

我在很多论坛上阅读了很多主题,我找到的答案是:

不可能

但是……“Cerberus”应用程序打开了我的 GPS……所以……这是可能的!

谁能帮我解决这个问题?

【问题讨论】:

标签: android gps


【解决方案1】:

不,这是不可能的,也不合适。您不能在没有用户权限的情况下管理用户的电话。用户必须进行交互才能启用 GPS。

来自 Play 商店:

“当您尝试本地化设备时,如果 GPS 关闭,Cerberus 会自动启用 GPS(仅适用于 Android ,您可以保护它免遭未经授权的卸载 - 应用配置中的更多信息。”

你可以这样做:

startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));

【讨论】:

  • @goodm :仅供参考,这并非不可能。但是,是的,它不合适。
  • 那么 olaCabs 的表现如何?在一个提示中,他们启用了 gps,而无需让用户进入 GPS 设置面板。
  • 可以向用户显示一个 gps 启用对话框。它是通过播放服务完成的。但用户必须提示它。就像在谷歌地图中一样。没有用户是不可能的实现和交互..
【解决方案2】:

我认为我们有更好的版本可以在不打开设置的情况下启用位置,就像谷歌地图一样。

它看起来像这样 -

在 gradle 中添加依赖 - 编译 'com.google.android.gms:play-services-location:10.0.1'

public class MapActivity extends AppCompatActivity {

    protected static final String TAG = "LocationOnOff";

 
    private GoogleApiClient googleApiClient;
    final static int REQUEST_LOCATION = 199;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.setFinishOnTouchOutside(true);

        // Todo Location Already on  ... start
        final LocationManager manager = (LocationManager) MapActivity.this.getSystemService(Context.LOCATION_SERVICE);
        if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(MapActivity.this)) {
            Toast.makeText(MapActivity.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
        }
        // Todo Location Already on  ... end

        if(!hasGPSDevice(MapActivity.this)){
            Toast.makeText(MapActivity.this,"Gps not Supported",Toast.LENGTH_SHORT).show();
        }

        if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(MapActivity.this)) {
            Log.e("TAG","Gps already enabled");
            Toast.makeText(MapActivity.this,"Gps not enabled",Toast.LENGTH_SHORT).show();
            enableLoc();
        }else{
            Log.e("TAG","Gps already enabled");
            Toast.makeText(MapActivity.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
        }
    }


    private boolean hasGPSDevice(Context context) {
        final LocationManager mgr = (LocationManager) context
                .getSystemService(Context.LOCATION_SERVICE);
        if (mgr == null)
            return false;
        final List<String> providers = mgr.getAllProviders();
        if (providers == null)
            return false;
        return providers.contains(LocationManager.GPS_PROVIDER);
    }

    private void enableLoc() {

        if (googleApiClient == null) {
            googleApiClient = new GoogleApiClient.Builder(MapActivity.this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                        @Override
                        public void onConnected(Bundle bundle) {

                        }

                        @Override
                        public void onConnectionSuspended(int i) {
                            googleApiClient.connect();
                        }
                    })
                    .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
                        @Override
                        public void onConnectionFailed(ConnectionResult connectionResult) {

                            Log.d("Location error","Location error " + connectionResult.getErrorCode());
                        }
                    }).build();
            googleApiClient.connect();
         }

         LocationRequest locationRequest = LocationRequest.create();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
         locationRequest.setInterval(30 * 1000);
         locationRequest.setFastestInterval(5 * 1000);
         LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                    .addLocationRequest(locationRequest);

         builder.setAlwaysShow(true);

         PendingResult<LocationSettingsResult> result =
                    LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
         result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(LocationSettingsResult result) {
                final Status status = result.getStatus();
                switch (status.getStatusCode()) {
                  case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                       try {
                           // Show the dialog by calling startResolutionForResult(),
                           // and check the result in onActivityResult().
                                status.startResolutionForResult(MapActivity.this, REQUEST_LOCATION);
                       } catch (IntentSender.SendIntentException e) {
                           // Ignore the error.
                       }
                       break;
                 }
             }
         });
     }

}

【讨论】:

  • 我喜欢这个结果,但是代码对我来说太长了......而且我在官方文档中没有看到它。
【解决方案3】:

曾经有一个漏洞可以让没有特殊权限的应用打开 GPS。从 2.3 开始,该漏洞不再存在(在大多数 ROM 中)。这是另一个讨论它的帖子,

How can I enable or disable the GPS programmatically on Android?

“启用 GPS”是一项安全设置,因此您必须拥有 WRITE_SECURE_SETTINGS 权限。但是,这是受签名保护的权限,因此除非使用制造商的平台证书进行签名,否则您的应用不会被授予此权限。

正确的做法是将用户转到位置设置页面,并让他们根据需要启用 GPS。例如,

Intent i = new
Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(i);

【讨论】:

    【解决方案4】:
        if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage(R.string.gps_disabled_message)
            .setCancelable(false)
            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        startActivity(intent);                  
                }
            })
            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });
            AlertDialog alert = builder.create();
            alert.show();
        }
    

    这会创建一个警报,并允许用户转到设置屏幕并点击返回按钮以直接返回您的应用。据我所知,power 小部件漏洞无法在 2.3 之后使用。

    【讨论】:

      【解决方案5】:

      使用此代码 //在setcontentView(xml)之后调用GPSON

       private void turnGPSOn() {
      
          String provider = android.provider.Settings.Secure.getString(
                  getContentResolver(),
                  android.provider.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);
          }
      }**
      

      【讨论】:

        【解决方案6】:

        GoogleApiClient弃用,我们需要使用 SettingsClient 和 GoogleApi 来启用 GPS,而无需像 Google 地图一样进入位置设置, OLA, Zomato 等。下面的代码支持从 4.4 或更低到 11+ 的任何 Android 版本

        gradle 文件中需要的依赖项:

        implementation 'com.google.android.gms:play-services-location:17.1.0'
        

        检查 GPS 状态开启或关闭:

        private static LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        public static boolean isGpsEnabled(){
                return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            }
        

        如果 GPS 已启用,那么我们将显示 toast 通知,否则将要求打开 GPS。

        //Defining constant request code, add in your activity class
        private static final int REQUEST_CHECK_SETTINGS = 111;
        
        if(!isGpsEnabled()){
                    LocationRequest locationRequest = LocationRequest.create();
                    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
                    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                            .addLocationRequest(locationRequest);
        
                builder.setAlwaysShow(true); //this displays dialog box like Google Maps with two buttons - OK and NO,THANKS
        
                Task<LocationSettingsResponse> task =
                        LocationServices.getSettingsClient(this).checkLocationSettings(builder.build());
        
                task.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
                    @Override
                    public void onComplete(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(
                                                YOUR_ACTIVITY.this,
                                                REQUEST_CHECK_SETTINGS);
                                    } 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;
                            }
                        }
                    }
                });
            } else {
                Toast.makeText(getApplicationContext(), "GPS is already Enabled!", Toast.LENGTH_SHORT).show();
            }
        }
        

        如果 GPS 未开启,则流将到达 RESOLUTION_REQUIRED 并调用 startResolutionForResult,由 onActivityResult 处理

        现在,添加 onActivityResult 方法 -

        @Override
            protected void onActivityResult(int requestCode, int resultCode, Intent data) {
                super.onActivityResult(requestCode, resultCode, data);
                final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
        
                switch (requestCode) {
                    case REQUEST_CHECK_SETTINGS:
                        switch (resultCode) {
                            case Activity.RESULT_OK:
                                // All required changes were successfully made
                                Toast.makeText(getApplicationContext(),"User has clicked on OK - So GPS is on", Toast.LENGTH_SHORT).show();
                                break;
                            case Activity.RESULT_CANCELED:
                                // The user was asked to change settings, but chose not to
                                Toast.makeText(getApplicationContext(),"User has clicked on NO, THANKS - So GPS is still off.", Toast.LENGTH_SHORT).show();
                                break;
                            default:
                                break;
                        }
                        break;
                }
            }
        

        如果 resultCode 为 RESULT_OK 表示用户允许打开 GPS,否则 RESULT_CANCELED,您可以再次询问或显示基本原理对话框。

        • 您可以将上面的代码包装在方法中,然后在需要的地方调用
        • 在构建 LocationRequest 时,您可以根据应用的需要设置 Interval、Priority、SmallestDisplacement、FastestInterval 等。
        • 我们使用了 Task api 而不是 PendingResult

        官方文档请参考-https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient

        【讨论】:

        • 我在 getSystemService 行收到错误“无法从静态上下文引用非静态服务”。如何解决?
        【解决方案7】:

        你可能想看看这个帖子

        How can I enable or disable the GPS programmatically on Android?

        这是从该线程复制的代码

        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);
            }
        }
        
        private void turnGPSOff(){
            String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
        
            if(provider.contains("gps")){ //if gps is enabled
                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);
        
        
           }
        }
        

        但不建议使用该解决方案,因为它可能不适用于 android 版本 > 2.3.. 请检查 cmets

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-29
          • 1970-01-01
          相关资源
          最近更新 更多