Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to detect if Google Fit app is installed and used by user?

I want to add step counter to my app. By now I'm using Google fit to measure user step count.

The problems I'm facing with is that not all devices has Google Fit app installed, and even if does - not all users register to app service (as client).

So the desired flow is:

  1. Detect if Google fit app is installed.
  2. If installed, check if user is registered to Google fit app.
  3. If installed and registered to Google fit app, check if user account type support's using fitness services. (recording data such as steps)
  4. If all above ok, check if the user has confirmed the `Google fit pop-up.

Basically I want to check if the user using fit app (using all the conditions above), if one fails then it will use the StepCount sensor on device (if exists), If sensor doesn't exist it will use the other sensors the achieve this goal.

Here is the code that I'm using to connect with Google Fit API:

private void buildFitnessClient() {
    // Create the Google API Client
    mClient = new GoogleApiClient.Builder(getContext())
            .addApi(Fitness.HISTORY_API)
            .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ))
            .addConnectionCallbacks(
                    new GoogleApiClient.ConnectionCallbacks() {

                        @Override
                        public void onConnected(Bundle bundle) {
                            Log.i(TAG, "Connected!!!");
                            // Now you can make calls to the Fitness APIs.
                            // Put application specific code here.


                            new getFitnessTask().execute();
                        }


                        @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() {
                        // Called whenever the API client fails to connect.
                        @Override
                        public void onConnectionFailed(ConnectionResult result) {
                            Log.i(TAG, "Connection failed. Cause: " + result.toString());
                            if (!result.hasResolution()) {
                                // Show the localized error dialog
                                if (getActivity() != null) {

                                    GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(),
                                            getActivity(), 0).show();
                                }
                                return;
                            }
                            // The failure has a resolution. Resolve it.
                            // Called typically when the app is not yet authorized, and an
                            // authorization dialog is displayed to the user.
                            if (!authInProgress) {

                                try {
                                    Log.i(TAG, "Attempting to resolve failed connection; activity; "+  getActivity());
                                    if (getActivity() != null) {

                                        authInProgress = true;
                                        result.startResolutionForResult(getActivity(),
                                                REQUEST_OAUTH);
                                    }
                                } catch (IntentSender.SendIntentException e) {
                                    Log.e(TAG,
                                            "Exception while starting resolution activity", e);
                                }
                            }
                        }
                    }
            )
            .build();
}

public void onActivityResult(int requestCode, int resultCode, Intent data){
    Log.e(TAG, "onActivityResult requestCode=" + requestCode + ", resultCode=" + resultCode);
    if (requestCode == REQUEST_OAUTH) {
        authInProgress = false;
        if (resultCode == Activity.RESULT_OK) {

            Log.e(TAG, "RESULT_OK");
            // Make sure the app is not already connected or attempting to connect
            if (!mClient.isConnecting() && !mClient.isConnected()) {
                mClient.connect();
            }
        } else if (resultCode == Activity.RESULT_CANCELED) {
            Log.e(TAG, "RESULT_CANCELED");
        }
    }
}


private class getFitnessTask extends AsyncTask<Void, Void, Integer> {
    ...
}
}

Need your help guys,

Thanks.

like image 754
sharonooo Avatar asked Dec 15 '15 14:12

sharonooo


2 Answers

You can call getPackageInfo() on the PackageManager. If it throws a PackageManager.NameNotFoundException it means that the app is not installed. If it doesn't throw an exception, google fit is installed

fun fitInstalled(context: Context): Boolean {
  val fitPackage = "com.google.android.apps.fitness"
  return try {
    if (Build.VERSION.SDK_INT >= 33) {
      context.packageManager.getPackageInfo(
        fitPackage,
        PackageManager.PackageInfoFlags.of(PackageManager.GET_ACTIVITIES.toLong())
      )
    } else {
      @Suppress("DEPRECATION")
      context.packageManager.getPackageInfo(
        fitPackage,
        PackageManager.GET_ACTIVITIES
      )
    }
    true
  } catch (e: PackageManager.NameNotFoundException) {
    false
  }
}

Additionally if you target Android 11+, you need to tell Android that you are querying the fit package in your AndroidManifest.xml:

<manifest ...>
  ...
  <queries>
    <package android:name="com.google.android.apps.fitness" />
  </queries>
</manifest>
like image 62
Paul Woitaschek Avatar answered Nov 12 '22 07:11

Paul Woitaschek


here is kotlin version

fun checkIfFitInstalled(): Boolean {
    try {
        applicationContext.packageManager.getPackageInfo("com.google.android.apps.fitness", PackageManager.GET_ACTIVITIES)
        return true
    } catch (e: Exception) {
        return false
    }
}
like image 1
ozkanpakdil Avatar answered Nov 12 '22 06:11

ozkanpakdil