LocationSettingsRequest对话框启用GPS - 跳过onActivityResult()

pez*_*pez 51 android dialog

我的应用程序的一部分需要位置服务,因此如果当前关闭位置,应用程序将提示用户启用它.下面是我正在做它:(也见于这个堆栈溢出的答案)

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,NobackDialog,onActivityResult()不运行.

我需要Android才能调用onActivityResult(),如果用户选择不打开位置服务,我可以适当地处理它.

谷歌的开发者页面(以及上面的代码)明确表示onActivityResult()应该调用它.任何人都知道为什么会被跳过?

我也不知道这一行的目的是什么:

final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);

谢谢!

编辑:关于我的应用程序结构的基本信息:

  • 这个代码被包含在内onResume()的一个方法Fragment,它实现GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListenerLocationListener接收位置更新.这里看到的例子.
  • 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)

  • 每次返回0 (3认同)

小智 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.startResolutionForResult(hostActivity,REQUEST_CHECK_SETTINGS); 并使用您的代码及其工作,而无需覆盖主要活动中的onActiivtyResult. (2认同)
  • 这应该是公认的答案。工作完美。 (2认同)

gia*_*ise 8

当您需要解决Status或 时ResolvableApiException,我建议您利用activity.registerForActivityResultAPI 代替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)

  • 现在应该将其标记为答案,旧标记的答案已经过时了。这是目前最新的方法。 (2认同)

Gho*_*mik 5

如果您想让结果返回片段而不是使用

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 次

最近记录:

5 年,10 月 前