如何在 Android 上打开 GPS
Posted
技术标签:
【中文标题】如何在 Android 上打开 GPS【英文标题】:How to turn on the GPS on Android 【发布时间】:2012-04-13 06:28:33 【问题描述】:我正在开发一个需要激活 GPS 的安卓应用。
我在很多论坛上阅读了很多主题,我找到的答案是:
不可能
但是……“Cerberus”应用程序打开了我的 GPS……所以……这是可能的!
谁能帮我解决这个问题?
【问题讨论】:
这是代码-[以编程方式打开或关闭 GPS。][1] [1]: ***.com/questions/4721449/… 【参考方案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
【讨论】:
以上是关于如何在 Android 上打开 GPS的主要内容,如果未能解决你的问题,请参考以下文章
如何检查我是不是在 android 4.4 及更高版本中以编程方式打开了 gps? [复制]
如何在 Android 中以编程方式启用禁用 GPS? [复制]
如何在不使用 GPS 的情况下获取 Android 设备的当前城市名称?