我的应用程序的一部分需要位置服务,因此如果当前关闭位置,应用程序将提示用户启用它.下面是我正在做它:(也见于这个堆栈溢出的答案)
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>()
{
@Override
public void onResult(LocationSettingsResult result)
{
final Status status = result.getStatus();
final LocationSettingsStates = result.getLocationSettingsStates();
switch (status.getStatusCode())
{
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
...
Log.d("onResult", "SUCCESS");
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
Log.d("onResult", "RESOLUTION_REQUIRED");
try
{
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(OuterClass.this, REQUEST_LOCATION);
}
catch (SendIntentException e)
{
// Ignore the 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.
...
Log.d("onResult", "UNAVAILABLE");
break;
}
}
});
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
// This log is never called
Log.d("onActivityResult()", Integer.toString(resultCode));
final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
switch (requestCode)
{
case REQUEST_LOCATION:
switch (resultCode)
{
case Activity.RESULT_OK:
{
// All required changes were successfully made
break;
}
case Activity.RESULT_CANCELED:
{
// The user was asked to change settings, but chose not to
break;
}
default:
{
break;
}
}
break;
}
}
Run Code Online (Sandbox Code Playgroud)
此代码运行良好,但onActivityResult()
始终跳过.无论用户按Yes
,No
或back
从Dialog
,onActivityResult()
不运行.
我需要Android才能调用onActivityResult()
,如果用户选择不打开位置服务,我可以适当地处理它.
谷歌的开发者页面(以及上面的代码)明确表示onActivityResult()
应该调用它.任何人都知道为什么会被跳过?
我也不知道这一行的目的是什么:
final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
谢谢!
编辑:关于我的应用程序结构的基本信息:
onResume()
的一个方法Fragment
,它实现GoogleApiClient.ConnectionCallbacks
, GoogleApiClient.OnConnectionFailedListener
和LocationListener
接收位置更新.这里看到的例子.onLocationChanged()
该Fragment
将有一个自定义的View
呼叫invalidate()
,并重新绘制自己的最新信息.Dan*_*ent 120
看起来主要的问题是你拥有Fragment中的所有代码,并且由于startResolutionForResult()
需要将一个Activity传递给它,Activity才能获得onActivityResult()
回调.
解决这个问题的一种方法是使用这里描述的技术,onActivityResult()
当结果进入时,从Activity中手动调用Fragment的方法.
我刚才有这个简单的例子.
首先,Activity添加了Fragment,并且还具有将结果传递onActivityResult()
给Fragment的功能:
override fun showEnableLocationSetting() {
activity?.let {
val locationRequest = LocationRequest.create()
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
val builder = LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest)
val task = LocationServices.getSettingsClient(it)
.checkLocationSettings(builder.build())
task.addOnSuccessListener { response ->
val states = response.locationSettingsStates
if (states.isLocationPresent) {
//Do something
}
}
task.addOnFailureListener { e ->
if (e is ResolvableApiException) {
try {
// Handle result in onActivityResult()
e.startResolutionForResult(it,
MainActivity.LOCATION_SETTING_REQUEST)
} catch (sendEx: IntentSender.SendIntentException) { }
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是Fragment,它包含显示对话框和处理结果的所有功能.在这个简单的例子中,我只使用Toast消息来验证它是否按预期工作.请注意,我在此处从您的问题中的代码所做的主要更改是使用getActivity()
获取调用所需的Activity引用startResolutionForResult()
.
companion object {
const val LOCATION_SETTING_REQUEST = 999
}
Run Code Online (Sandbox Code Playgroud)
以下是可视化结果,如果禁用了位置模式,则首先显示对话框:
然后,如果用户单击否,结果将从活动传递到片段,片段显示Toast:
当用户单击"是"但具有成功结果并启用"位置模式"时,同样如此:
请注意,在Activity中保留所有这些功能可能是更好的选择,然后在结果进入时调用Fragment中的公共方法.
这是完整的代码,用于保持Activity中的功能.当然,在此解决方案中,您需要在Fragment中添加一个调用,以便在调用后更新位置模式的状态onActivityResult()
.
public class MainActivity extends AppCompatActivity{
LocationFragment lFrag;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lFrag = LocationFragment.newInstance();
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, lFrag).commit();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == LocationFragment.REQUEST_LOCATION){
lFrag.onActivityResult(requestCode, resultCode, data);
}
else {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 35
您需要将此添加到结果回调中:
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
fragment.startIntentSenderForResult(status.getResolution().getIntentSender(), REQUEST_CHECK_SETTINGS, null, 0, 0, 0, null);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
Run Code Online (Sandbox Code Playgroud)
onActivityResult
将在您的片段上调用,您无需在活动中手动调用它.这基本上是如何startResolutionForResult
运作的.
当您需要解决Status
或 时ResolvableApiException
,我建议您利用activity.registerForActivityResult
API 代替startResolutionForResult
:
ActivityResultLauncher<IntentSenderRequest> launcher = activity.registerForActivityResult(
new ActivityResultContracts.StartIntentSenderForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
// All required changes were successfully made
} else {
// The user was asked to change settings, but chose not to
}
}
});
IntentSenderRequest intentSenderRequest = new IntentSenderRequest.Builder(exception.getResolution()).build();
launcher.launch(intentSenderRequest);
Run Code Online (Sandbox Code Playgroud)
您正在使用 Java,但如果需要 Kotlin:
val launcher = activity.registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
// User accepted
} else {
// User didn't accepted
}
}
val intentSenderRequest = IntentSenderRequest.Builder(exception.resolution).build()
launcher.launch(intentSenderRequest)
Run Code Online (Sandbox Code Playgroud)
如果您想让结果返回片段而不是使用
startIntentSenderForResult(status.getResolution().getIntentSender(), REQUEST_CODE_LOCATION_SETTING, null, 0, 0, 0, null);
Run Code Online (Sandbox Code Playgroud)
代替 status.startResolutionForResult(YourActivity, LOCATION_REQUEST);
使用上述方法只会将结果传递回您的片段。
归档时间: |
|
查看次数: |
38879 次 |
最近记录: |