LocationSettingsRequest对话框 - onActivityResult()跳过 [英] LocationSettingsRequest dialog - onActivityResult() skipped

查看:802
本文介绍了LocationSettingsRequest对话框 - onActivityResult()跳过的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序的一部分,需要定位服务,所以如果位置当前处于关闭状态,应用程序将提示用户启用它。 这里是我如何做它:(也见于这个的堆栈溢出的答案)

Part of my app requires location services, so if location is currently turned off, the app will prompt the user to enable it. Here is how I am doing it: (Also seen in this Stack Overflow answer)

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

这code效果很好,但是, onActivityResult()总是被忽略。不管是不是用户presses 返回对话框 onActivityResult()不运行。

This code works well, however, onActivityResult() is always skipped. Whether or not the user presses Yes, No, or back from the Dialog, onActivityResult() doesn't run.

我必须使用Android调用 onActivityResult()如果用户选择不打开定位服务的话,我能妥善处理这个问题。

I need Android to call onActivityResult() so if the user chooses not to turn on location services, I can handle it appropriately.

谷歌的开发者页面(和code以上)明确地说, onActivityResult()应该叫。任何人都知道它为什么被跳过?

Google's developer page (and the code above) explicitly says that onActivityResult() should be called. Anyone know why it's being skipped?

我也不知道这行的目的是:

I also don't know what the purpose of this line is:

最后LocationSettingsStates规定= LocationSettingsStates.fromIntent(数据);

谢谢!

编辑:在我的应用程序的结构,基本信息:

Basic information on the structure of my app:

  • 这code包含的片段它实现<$ c中的 onResume()方法中$ C> GoogleApiClient.ConnectionCallbacks , GoogleApiClient.OnConnectionFailedListener LocationListener的来接收位置更新。举例看到这里
  • onLocationChanged()片段将有一个自定义的查看呼叫无效()并重新绘制自己的最新信息。
  • This code is contained within the onResume() method of a Fragment which implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, and LocationListener to receive location updates. Example seen here.
  • In onLocationChanged() the Fragment will have a custom View call invalidate() and re-draw itself with updated information.

推荐答案

它看起来像的主要问题是,你把所有的code的片段,并且因为 startResolutionForResult()需要传递给它的一个活动,活动是得到 onActivityResult()回调。

It looks like the main issue is that you have all of the code in a Fragment, and since startResolutionForResult() needs an Activity passed into it, the Activity is what gets the onActivityResult() callback.

要解决的方法之一是使用描述的技术<一href="http://stackoverflow.com/questions/22602988/google-login-not-working-properly-on-android-fragment">here,手动调用片段的 onActivityResult()的活动方法,当结果的原因。

One way to get around that is to use the technique described here, manually call the Fragment's onActivityResult() method from the Activity when the result comes in.

我刚刚得到这个简单的例子工作。

I just got this simple example working.

首先,活动,它增加了片段,同时还具有的功能得以传承的结果 onActivityResult()的片段:

First, the Activity, which adds the Fragment, and also has functionality to pass along the result of onActivityResult() to the Fragment:

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

下面是片段,它包含所有的功能,以显示对话框,和处理的结果。在这个简单的例子,我只是用吐司消息来验证它是否工作正常。请注意,我在这里从code在你的问题提出的主要变化是采用 getActivity()来获得所需调用活动参考 startResolutionForResult()

Here is the Fragment, which contains all of the functionality to show the dialog, and handle the result. In this simple example I just used Toast messages to verify that it is working as expected. Note that the main change that I've made here from the code in your question is the use of getActivity() to get the Activity reference needed for the call to startResolutionForResult().

public class LocationFragment extends Fragment
        implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {


    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    PendingResult<LocationSettingsResult> result;
    final static int REQUEST_LOCATION = 199;

    public static LocationFragment newInstance() {
        LocationFragment fragment = new LocationFragment();
        return fragment;
    }

    public LocationFragment() {
        // Required empty public constructor
    }

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).build();
        mGoogleApiClient.connect();

        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_location, container, false);
    }


    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public void onConnected(Bundle bundle) {

        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(30 * 1000);
        mLocationRequest.setFastestInterval(5 * 1000);

        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(mLocationRequest);
        builder.setAlwaysShow(true);

        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 state = result.getLocationSettingsStates();
                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        // All location settings are satisfied. The client can initialize location
                        // requests here.
                        //...
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        // Location settings are not satisfied. But could be fixed by showing the user
                        // a dialog.
                        try {
                            // Show the dialog by calling startResolutionForResult(),
                            // and check the result in onActivityResult().
                            status.startResolutionForResult(
                                    getActivity(),
                                    REQUEST_LOCATION);
                        } catch (IntentSender.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.
                        //...
                        break;
                }
            }
        });

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        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
                        Toast.makeText(getActivity(), "Location enabled by user!", Toast.LENGTH_LONG).show();
                        break;
                    }
                    case Activity.RESULT_CANCELED:
                    {
                        // The user was asked to change settings, but chose not to
                        Toast.makeText(getActivity(), "Location not enabled, user cancelled.", Toast.LENGTH_LONG).show();
                        break;
                    }
                    default:
                    {
                        break;
                    }
                }
                break;
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }

}

下面是结果可视化,首先是所示的对话框,如果位置模式被禁用:

Here are the results visually, first the dialog is shown if Location Mode is disabled:

之后,如果用户单击否,结果是从活动的片段,其中显示了一个士传递:

Then, if the user clicks No, the result is passed from the Activity to the Fragment, which shows a Toast:

同样的事情,当用户点击是的,但有一个成功的结果,并定位模式已启用:

Same thing when the user clicks Yes, but with a success result, and Location Mode is enabled:

请注意,这可能是一个更好的选择,只是把所有的活动这个功能,然后调用到的片段的公共方法当结果的原因。

Note that it might be a better option to just keep all of this functionality in the Activity, and then call into a public method in the Fragment when the result comes in.

下面是完全正常工作code的保持功能活性的影响。 当然,在这个解决方案中,您需要添加一个调用到片段后, onActivityResult更新位置模式的状态()之称。

Here is fully working code for keeping the functionality in the Activity. Of course in this solution, you would need to add a call into the Fragment to update the state of Location Mode after onActivityResult() is called.

public class MainActivity extends AppCompatActivity
        implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {


    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    PendingResult<LocationSettingsResult> result;
    final static int REQUEST_LOCATION = 199;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).build();
        mGoogleApiClient.connect();

    }

    @Override
    public void onConnected(Bundle bundle) {

        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(30 * 1000);
        mLocationRequest.setFastestInterval(5 * 1000);

        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(mLocationRequest);
        builder.setAlwaysShow(true);

        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 state = result.getLocationSettingsStates();
                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        // All location settings are satisfied. The client can initialize location
                        // requests here.
                        //...
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        // Location settings are not satisfied. But could be fixed by showing the user
                        // a dialog.
                        try {
                            // Show the dialog by calling startResolutionForResult(),
                            // and check the result in onActivityResult().
                            status.startResolutionForResult(
                                    MainActivity.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.
                        //...
                        break;
                }
            }
        });

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        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
                        Toast.makeText(MainActivity.this, "Location enabled by user!", Toast.LENGTH_LONG).show();
                        break;
                    }
                    case Activity.RESULT_CANCELED:
                    {
                        // The user was asked to change settings, but chose not to
                        Toast.makeText(MainActivity.this, "Location not enabled, user cancelled.", Toast.LENGTH_LONG).show();
                        break;
                    }
                    default:
                    {
                        break;
                    }
                }
                break;
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }
}

这篇关于LocationSettingsRequest对话框 - onActivityResult()跳过的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆