2016-04-10 2 views
1

Я искал решение этого вопроса, и я наткнулся на несколько ответов, которые не соответствовали прецеденту. sample code from Google отлично работает, если импортирован как есть, но код находится в действии и является беспорядочным, если вы хотите интегрироваться в настоящий проект, где код в идеале должен быть в фрагменте.Как реализовать счетчик шагов Google Fit в пределах фрагмента

Этот вопрос с enableAutoManage функциональность и что делать в свежем установке случае, где построен GoogleApiClient но экран аутентификации/счета-подборщика еще не сделано, и вы в конечном итоге с подключением провалившегося на GoogleApiClient. Я собираюсь ответить на это полностью, внизу.

ответ

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

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

Flow:

  1. Запуск приложения
  2. клиент API Google построен, в результате чего соединение не удалось обратного вызова, но и вызывает диалоговое окно Выбор учетной записи появится
  3. счета определена, onActivityResult от активности называется, результат отправляется onActivityResult в Фрагмент
  4. клиент API Google перезапускается (stopAutoManage, разъединение, подключение)
  5. Logging начинает STEP_COUNT_CUMULATIVE или введите любые другие данные, которые вы выбираете

Это работает и тестируется много, пожалуйста, спросите, если вы не знаете, о чем

Смежные вопросы