我一直在寻找解决方案,我遇到了几个不适合用例的答案。如果按原样导入,sample code from Google可以正常工作,但代码位于Activity中,如果要集成到一个理想情况下代码片段中的实际项目中,则代码很麻烦。
问题在于 enableAutoManage 功能以及如何在新安装的情况下执行googleApiClient,但身份验证/帐户选择屏幕尚未完成且最终导致连接失败在googleApiClient上。我将在下面全部回答这个问题。
答案 0 :(得分:3)
以下示例活动会将GoogleFit_Fragment加载到FrameLayout中:
public class Main_Activity extends AppCompatActivity {
public static int USER_AUTHORISED_REQUEST_CODE = 5;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
This will load the GoogleFit_Fragment into the FrameLayout,
which will cause the buildFitnessClient() function to be called from the Fragment,
which will cause this Activity to popup the authentication screen
*/
getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.fade_in, R.anim.fade_out)
.replace(R.id.fragment_container, new GoogleFit_Fragment()).commit();
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
/*
The result of the account chooser is here,
send it to the fragment so we can handle it inside
*/
fragmentReplace.onActivityResult(USER_AUTHORISED_REQUEST_CODE, resultCode, data);
}
}
GoogleFit_Fragment:
public class GoogleFit_Fragment extends Fragment {
public static final String TAG = "Sample";
private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 1;
private GoogleApiClient googleApiFitnessClient;
private OnDataPointListener mListener;
private View fragmentView;
private Activity parentActivity;
@Override
public void onStop() {
super.onStop();
if (googleApiFitnessClient != null) {
Log.d(TAG, "onStop REACHED, client not null and is connected");
googleApiFitnessClient.stopAutoManage(getActivity());
googleApiFitnessClient.disconnect();
}
}
@Override
public void onResume() {
super.onResume();
if (googleApiFitnessClient != null) {
Log.d(TAG, "onResume REACHED, client not null");
googleApiFitnessClient.stopAutoManage(getActivity());
googleApiFitnessClient.disconnect();
googleApiFitnessClient.connect();
} else {
Log.d(TAG, "onResume REACHED, client null, buildingClient");
buildFitnessClient();
googleApiFitnessClient.connect();
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof Activity) {
parentActivity = (Activity) context;
}
}
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
fragmentView = inflater.inflate(R.layout.fragment_google_fit, container, false);
initializeLogging();
if (!checkPermissions()) {
requestPermissions();
}
return fragmentView;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == Main_Activity.USER_AUTHORISED_REQUEST_CODE && googleApiFitnessClient != null) {
Log.d(TAG, "Activity result finished authorissation, disconnect the client and reconnect");
googleApiFitnessClient.stopAutoManage(getActivity());
googleApiFitnessClient.disconnect();
googleApiFitnessClient.connect();
}
}
private void buildFitnessClient() {
googleApiFitnessClient = new GoogleApiClient.Builder(parentActivity)
.addApi(Fitness.SENSORS_API)
// .addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
// .addScope(new Scope(Scopes.FITNESS_NUTRITION_READ_WRITE))
// .addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs.
findFitnessDataSources();
}
@Override
public void onConnectionSuspended(int i) {
// If your connection to the sensor gets lost at some point,
// you'll be able to determine the reason and react to it here.
if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Connection lost. Cause: Network Lost.");
} else if (i
== GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG,
"Connection lost. Reason: Service Disconnected");
}
}
}
)
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "Connection failed! " + connectionResult.getErrorMessage());
}
}
)
.enableAutoManage((FragmentActivity) parentActivity, 0, new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Google Play services connection failed. Cause: " +
result.toString());
}
})
.build();
}
private void findFitnessDataSources() {
// Note: Fitness.SensorsApi.findDataSources() requires the ACCESS_FINE_LOCATION permission.
Fitness.SensorsApi.findDataSources(googleApiFitnessClient, new DataSourcesRequest.Builder()
// At least one datatype must be specified.
.setDataTypes(DataType.TYPE_STEP_COUNT_CUMULATIVE)
// Can specify whether data type is raw or derived.
.setDataSourceTypes(DataSource.TYPE_RAW)
.build())
.setResultCallback(new ResultCallback<DataSourcesResult>() {
@Override
public void onResult(DataSourcesResult dataSourcesResult) {
Log.i(TAG, "Result: " + dataSourcesResult.getStatus().toString());
for (DataSource dataSource : dataSourcesResult.getDataSources()) {
Log.i(TAG, "Data source found: " + dataSource.toString());
Log.i(TAG, "Data Source type: " + dataSource.getDataType().getName());
//Let's register a listener to receive Activity data!
if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_CUMULATIVE)
&& mListener == null) {
Log.i(TAG, "Data source for " + dataSource.getDataType() + " found! Registering.");
registerFitnessDataListener(dataSource,
DataType.TYPE_STEP_COUNT_CUMULATIVE);
}
}
}
});
}
/**
* Register a listener with the Sensors API for the provided {@link DataSource} and
* {@link DataType} combo.
*/
private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
mListener = new OnDataPointListener() {
@Override
public void onDataPoint(DataPoint dataPoint) {
for (Field field : dataPoint.getDataType().getFields()) {
Value val = dataPoint.getValue(field);
Log.i(TAG, "Detected DataPoint field: " + field.getName());
Log.i(TAG, "Detected DataPoint value: " + val);
}
}
};
Fitness.SensorsApi.add(
googleApiFitnessClient,
new SensorRequest.Builder()
.setDataSource(dataSource) // Optional but recommended for custom data sets.
.setDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE) // Can't be omitted.
.setSamplingRate(1, TimeUnit.SECONDS)
.build(),
mListener)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.i(TAG, "Listener registered!");
} else {
Log.i(TAG, "Listener not registered.");
}
}
});
}
private void initializeLogging() {
/*
Not really needed, you can just log to Logcat without having a view in this fragment
*/
LogWrapper logWrapper = new LogWrapper();
Log.setLogNode(logWrapper);
MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
logWrapper.setNext(msgFilter);
LogView logView = (LogView) fragmentView.findViewById(R.id.sample_logview);
logView.setTextAppearance(parentActivity, R.style.Log);
logView.setBackgroundColor(Color.WHITE);
msgFilter.setNext(logView);
Log.i(TAG, "Ready");
}
/**
* Return the current state of the permissions needed.
*/
private boolean checkPermissions() {
int permissionState = ActivityCompat.checkSelfPermission(parentActivity,
Manifest.permission.ACCESS_FINE_LOCATION);
return permissionState == PackageManager.PERMISSION_GRANTED;
}
private void requestPermissions() {
boolean shouldProvideRationale =
ActivityCompat.shouldShowRequestPermissionRationale(parentActivity,
Manifest.permission.ACCESS_FINE_LOCATION);
if (shouldProvideRationale) {
Log.i(TAG, "Displaying permission rationale to provide additional context.");
Snackbar.make(
fragmentView.findViewById(R.id.main_activity_view),
R.string.permission_rationale,
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View view) {
// Request permission
ActivityCompat.requestPermissions(parentActivity,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.BODY_SENSORS},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
})
.show();
} else {
Log.i(TAG, "Requesting permission");
ActivityCompat.requestPermissions(parentActivity,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.BODY_SENSORS},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
Log.i(TAG, "onRequestPermissionResult");
if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
if (grantResults.length <= 0) {
Log.i(TAG, "User interaction was cancelled.");
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
buildFitnessClient();
} else {
Snackbar.make(
fragmentView.findViewById(R.id.main_activity_view),
R.string.permission_denied_explanation,
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.settings, new View.OnClickListener() {
@Override
public void onClick(View view) {
// Build intent that displays the App settings screen.
Intent intent = new Intent();
intent.setAction(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package",
BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
})
.show();
}
}
}
}
<强>流量:强>
这很有效,经过了大量测试,请询问您是否不确定