退出片段的父 activity 后,Google Fit 步数 return 为零(注销)

GoogleFit Steps Count return zero after exiting the fragment's parent activity (signout)

我正在使用 GoogleFit Api 计算每日步数。我得到了正确的结果。但是当我退出应用程序时(在这种情况下,应用程序退出 Googlefit 片段的父级 activity) 再次登录后,我再次访问相同的片段,但 Googlefit returns stepsCount 为零并且在 result.await 处超时。 这是我的代码。 GoogleFitFragment.java

package com.example.mudasirrao.mvvm.Fragments.GoogleFitFragments;


import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.mudasirrao.mvvm.R;
import com.example.mudasirrao.mvvm.ViewModel.GoogleFitViewModels.GoogleFitViewModel;
import com.example.mudasirrao.mvvm.databinding.FragmentGoogleFitBinding;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.fitness.ConfigApi;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.result.DataTypeResult;

public class GoogleFitFragment extends Fragment {

GoogleFitViewModel googleFitViewModel;

public GoogleFitFragment() {
}

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

    FragmentGoogleFitBinding fragmentGoogleFitBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_google_fit, container, false);
    View view = fragmentGoogleFitBinding.getRoot();
    googleFitViewModel = new GoogleFitViewModel(getActivity(), fragmentGoogleFitBinding);
    fragmentGoogleFitBinding.setGoogleFitFragmentViewModel(googleFitViewModel);
    return view;

}

}

GoogleFitViewModel.java

package com.example.mudasirrao.mvvm.ViewModel.GoogleFitViewModels;

import android.content.Context;
import android.content.SharedPreferences;
import android.databinding.ObservableField;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.example.mudasirrao.mvvm.CallBacks.CallBackGoogleFitClient;
import com.example.mudasirrao.mvvm.DataManager.GoogleFitDataManager;
import com.example.mudasirrao.mvvm.databinding.FragmentGoogleFitBinding;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.fitness.ConfigApi;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.data.DataSet;
import com.google.android.gms.fitness.data.DataType;
import com.google.android.gms.fitness.data.Field;
import com.google.android.gms.fitness.result.DailyTotalResult;

import java.util.concurrent.TimeUnit;

import static android.content.Context.MODE_PRIVATE;


public class GoogleFitViewModel {

private Context context;
private FragmentGoogleFitBinding fragmentGoogleFitBinding;
public final ObservableField<String> steps = new ObservableField<>();
public GoogleApiClient localGoogleApiClient;
String dailySteps;

public GoogleFitViewModel(Context context, final FragmentGoogleFitBinding fragmentGoogleFitBinding) {

    this.context = context;
    this.fragmentGoogleFitBinding = fragmentGoogleFitBinding;
    SharedPreferences prefs = context.getSharedPreferences("dailySteps", MODE_PRIVATE);
    dailySteps = prefs.getString("daily_steps", null);

    if (dailySteps != null) {

        steps.set(dailySteps);
        GoogleFitDataManager.singletonObject(context).buildFitnessClient(new CallBackGoogleFitClient() {

            @Override
            public void onResponse(GoogleApiClient googleApiClient) {

                localGoogleApiClient = googleApiClient;
                if (googleApiClient != null) {

                    new VerifyDataTask().execute(localGoogleApiClient);
                    fragmentGoogleFitBinding.setGoalLayout.animate().alpha(0.2f).setDuration(1000);
                    enableDisableLayout(false);
                    fragmentGoogleFitBinding.previewImage.setVisibility(View.GONE);
                    fragmentGoogleFitBinding.saveButton.setText("Edit");
                    fragmentGoogleFitBinding.saveButton.setTag("disabled_edit");
                    fragmentGoogleFitBinding.goalProgressLayout.setVisibility(View.VISIBLE);
                    fragmentGoogleFitBinding.goalText.setText("Take " + steps.get() + " steps a day");

                }

            }

        });

    } else {

        steps.set("0000");
        fragmentGoogleFitBinding.setGoalLayout.animate().alpha(1.0f).setDuration(3000);

    }

}

public void onClickStepsButton1(View view) {
    steps.set("2000");
}

public void onClickStepsButton2(View view) {
    steps.set("8000");
}

public void onClickStepsButton3(View view) {
    steps.set("10000");
}

public void onClickStepsButton4(View view) {
    steps.set("13000");
}

public void onClickSave(View view) {

    if ((Integer.valueOf(steps.get()) > 0)) {

        if (fragmentGoogleFitBinding.saveButton.getTag() == null) {

            GoogleFitDataManager.singletonObject(context).buildFitnessClient(new CallBackGoogleFitClient() {
                @Override
                public void onResponse(GoogleApiClient googleApiClient) {
                    localGoogleApiClient = googleApiClient;
                    if (googleApiClient != null) {

                        new VerifyDataTask().execute(localGoogleApiClient);
                        fragmentGoogleFitBinding.setGoalLayout.animate().alpha(0.2f).setDuration(1000);
                        enableDisableLayout(false);
                        fragmentGoogleFitBinding.previewImage.setVisibility(View.GONE);
                        fragmentGoogleFitBinding.saveButton.setText("Edit");
                        fragmentGoogleFitBinding.saveButton.setTag("disabled_edit");
                        fragmentGoogleFitBinding.goalProgressLayout.setVisibility(View.VISIBLE);

                    }

                }
            });

        } else {

            if (fragmentGoogleFitBinding.saveButton.getTag().equals("disabled_edit")) {

                fragmentGoogleFitBinding.setGoalLayout.animate().alpha(1.0f).setDuration(1000);
                enableDisableLayout(true);
                fragmentGoogleFitBinding.saveButton.setTag("enabled_edit");
                fragmentGoogleFitBinding.saveButton.setText("Save");

            } else if (fragmentGoogleFitBinding.saveButton.getTag().equals("enabled_edit")) {

                new VerifyDataTask().execute(localGoogleApiClient);
                fragmentGoogleFitBinding.setGoalLayout.animate().alpha(0.2f).setDuration(1000);
                enableDisableLayout(false);
                fragmentGoogleFitBinding.saveButton.setText("Edit");
                fragmentGoogleFitBinding.saveButton.setTag("disabled_edit");

            }

        }

        fragmentGoogleFitBinding.goalText.setText("Take " + steps.get() + " steps a day");

    } else

        Toast.makeText(context, "Please Select Steps", Toast.LENGTH_SHORT).show();

}

protected void renderStepsProgress(int stepsTaken) {

    saveDailyStepsInSharedPref(steps.get());
    int percentage = (int) (((double) stepsTaken / (double) Integer.valueOf(steps.get())) * 100);
    if (percentage > 100) {
        percentage = 100;
    }
    fragmentGoogleFitBinding.waveLoadingView.setCenterTitle(String.valueOf(percentage) + " %");
    fragmentGoogleFitBinding.waveLoadingView.setProgressValue(percentage);
    fragmentGoogleFitBinding.stepsTakenText.setText("You have taken " + String.valueOf(stepsTaken) + " steps today");

}

private void enableDisableLayout(Boolean visibility) {

    View child;
    for (int i = 0; i < fragmentGoogleFitBinding.stepButtonLayout1.getChildCount(); i++) {

        child = fragmentGoogleFitBinding.stepButtonLayout1.getChildAt(i);
        child.setEnabled(visibility);

    }
    for (int i = 0; i < fragmentGoogleFitBinding.stepButtonLayout2.getChildCount(); i++) {

        child = fragmentGoogleFitBinding.stepButtonLayout2.getChildAt(i);
        child.setEnabled(visibility);

    }

}

private void saveDailyStepsInSharedPref(String dailySteps) {
    SharedPreferences.Editor editor = context.getSharedPreferences("dailySteps", MODE_PRIVATE).edit();
    editor.putString("daily_steps", dailySteps);
    editor.apply();
}

private class VerifyDataTask extends AsyncTask<GoogleApiClient, Void, Integer> {

    @Override
    protected Integer doInBackground(GoogleApiClient... params) {


        int total = 0;

        PendingResult<DailyTotalResult> result = Fitness.HistoryApi.readDailyTotal(params[0], DataType.TYPE_STEP_COUNT_DELTA);
        DailyTotalResult totalResult = result.await(30, TimeUnit.SECONDS);
        if (totalResult.getStatus().isSuccess()) {

            DataSet totalSet = totalResult.getTotal();
            total = totalSet.isEmpty()
                    ? 0
                    : totalSet.getDataPoints().get(0).getValue(Field.FIELD_STEPS).asInt();

        } else {

            Log.d("steps_count_error", "There was a problem getting the step count!!");

        }

        return total;

    }

    protected void onPostExecute(Integer result) {

        renderStepsProgress(result);

    }

}

}

GoogleFitDataManager.java

package com.example.mudasirrao.mvvm.DataManager;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.widget.Toast;

import com.example.mudasirrao.mvvm.CallBacks.CallBackGoogleFitClient;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.FitnessStatusCodes;
import com.google.android.gms.fitness.data.DataType;

import static com.bumptech.glide.gifdecoder.GifHeaderParser.TAG;


public class GoogleFitDataManager {

    private static GoogleFitDataManager googleFitDataManager;
    private GoogleApiClient googleApiClient = null;
    private Context context;

    public GoogleFitDataManager(Context context) {

        this.context = context;

    }

    public static GoogleFitDataManager singletonObject(Context context) {

        if (googleFitDataManager == null) {

            googleFitDataManager = new GoogleFitDataManager(context);

        }

        return googleFitDataManager;
    }

    public void buildFitnessClient(final CallBackGoogleFitClient callBackGoogleFitClient) {

        if (googleApiClient == null) {

            googleApiClient = new GoogleApiClient.Builder(context)
                    .addApi(Fitness.HISTORY_API)
                    .addApi(Fitness.RECORDING_API)
                    .addApi(Fitness.CONFIG_API)
                    .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {

                                                @Override
                                                public void onConnected(@Nullable Bundle bundle) {
                                                    subscribeGoogleFit(googleApiClient);
                                                    callBackGoogleFitClient.onResponse(googleApiClient);

                                                }

                                                @Override
                                                public void onConnectionSuspended(int i) {

                                                    if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {

                                                        Toast.makeText(context, "Connection lost.  Cause: Network Lost.", Toast.LENGTH_SHORT).show();

                                                    } else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {

                                                        Toast.makeText(context, "Connection lost.  Reason: Service Disconnected", Toast.LENGTH_SHORT).show();

                                                    }
                                                }
                                            }
                    )
                    .enableAutoManage((FragmentActivity) context, 0, new GoogleApiClient.OnConnectionFailedListener() {
                        @Override
                        public void onConnectionFailed(ConnectionResult result) {

                            Log.i("TAG", "Google Play services connection failed. Cause: " + result.toString());
                            Toast.makeText(context, "Exception while connecting to Google Play services: " + result.getErrorMessage(), Toast.LENGTH_SHORT).show();

                        }
                    })
                    .build();

        } else {
            subscribeGoogleFit(googleApiClient);
            callBackGoogleFitClient.onResponse(googleApiClient);
        }

    }

    public void subscribeGoogleFit(GoogleApiClient client) {

        Fitness.RecordingApi.subscribe(client, DataType.TYPE_STEP_COUNT_DELTA)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {

                        if (status.isSuccess()) {

                            if (status.getStatusCode() == FitnessStatusCodes.SUCCESS_ALREADY_SUBSCRIBED) {

                                Log.i(TAG, "Existing subscription for activity detected.");

                            } else {

                                Log.i(TAG, "Successfully subscribed!");

                            }
                        } else {

                            Log.i(TAG, "There was a problem subscribing.");

                        }

                    }
                });

    }

}

我正在做的是创建 class 的静态对象,我在其中制作 googlefit 客户端。在这种情况下,当我退出 Activity 时,由于片段的 onDestroy 中的 enableAutoManage,对象没有被破坏并且 googlefit 客户端断开连接。根据我的检查,我没有再次连接到 googleFit 客户端。

我删除了该对象作为静态对象,现在我将 API 客户端 class 对象与我的片段所在的 activity 的生命周期保持一致。我还删除了 enableAutoManage,现在自己连接和断开 API 客户端。