如何在安卓开启GPS定位功能。

19

我正在开发一个需要激活GPS的Android应用程序。

我在很多论坛上阅读了很多相关话题,得到的答案是:

不可能

但是... "Cerberus"应用程序可以开启我的GPS... 所以...这是有可能的!

有人能帮助我吗?


这是代码- 编程打开或关闭GPS。 - Rajkiran
7个回答

22

不,这是不可能的,也不合适。您不能未经用户授权就管理其手机。用户必须进行交互才能启用GPS。

来自Play商店:

"Cerberus会在您尝试定位设备时自动启用GPS(仅适用于Android < 2.3.3),并且您可以在应用程序配置中保护其免受未经授权的卸载-有关更多信息,请参阅该应用程序的配置"

您可以像这样做:

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

1
@goodm:FYI,这不是不可能的。但是是不合适的。 - Rajkiran
3
olaCabs最近怎么样了?他们在一个单一提示中启用了GPS,而不会将用户发送到GPS设置面板。 - Alpesh
可以向用户显示启用GPS的对话框。这是通过Play服务完成的。但是用户必须提示它。就像在谷歌地图中一样。如果没有用户的认识和交互,这是不可能做到的。 - Samir Alakbarov

16

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

它会看起来像这样 -

enter image description here

在gradle中添加依赖 - compile '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;
                 }
             }
         });
     }

}

1
我喜欢这个结果,但是对我来说代码太长了... 而且我在官方文档中没有看到它。 - Sam Chen

13

之前存在一个漏洞,允许应用程序在没有特殊权限的情况下打开GPS。但是从2.3版本开始(在大多数ROM中),此漏洞已经不存在了。这里有另一篇帖子详细讨论了它:

如何在Android上以编程方式启用或禁用GPS?

"GPS已启用"是一个安全设置,因此您必须具有WRITE_SECURE_SETTINGS权限。但是,这是一个受签名保护的权限,因此除非您的应用程序使用制造商的平台证书签名,否则您将无法被授予此权限。

正确的做法是将用户发送到位置设置页面,然后让他们自行决定是否启用GPS,例如:

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

5
    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 widget漏洞在2.3以后不再有效。


2

使用以下代码: //在setContentView(xml)之后调用turnGPSON

 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);
    }
}**

2

GoogleApiClient已被废弃,我们需要使用SettingsClient和GoogleApi来使GPS无需进入位置设置,就像Google Maps、OLA、Zomato等应用程序一样。下面的代码支持Android 4.4或更低版本至11+的任何版本。

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时,您可以根据应用程序的要求设置间隔、优先级、最小位移、最快间隔等。
  • 我们使用了Task API而不是PendingResult。

有关官方文档,请参阅 - https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient


我在那个getSystemService那一行收到了“非静态服务不能从静态上下文引用”的错误。如何解决? - GeneCode

1

你可能想要查看这个主题

我怎样才能在Android上通过编程启用或禁用GPS?

这里是从那个主题复制的代码

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 上使用。请务必查看评论。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接