草庐IT

android - 如何使用 Google Fit Android API 获取步数的数据源?

coder 2023-12-11 原文

我正在尝试使用 Google Fit API 在我的应用中获取步数。但除了位置之外,我没有得到任何数据源。如何获取步数的数据源? 我已经坚持了 4 天多了。请帮我解决这个问题。谢谢。下面是我正在使用的代码

public class Home extends BaseActivity {
  private static String TAG = "HOME Activity";
  private static final int REQUEST_OAUTH = 1;

  /**
   * Track whether an authorization activity is stacking over the current activity, i.e. when
   * a known auth error is being resolved, such as showing the account chooser or presenting a
   * consent dialog. This avoids common duplications as might happen on screen rotations, etc.
   */
  private static final String AUTH_PENDING = "auth_state_pending";
  private boolean authInProgress = false;

  private GoogleApiClient mClient = null;
  private OnDataPointListener mListener;

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


    if (savedInstanceState != null) {
      authInProgress = savedInstanceState.getBoolean(AUTH_PENDING);
    }

    buildFitnessClient();


  }

  private void findFitnessDataSources() {
    // [START find_data_sources]
    Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
        // At least one datatype must be specified.
        .setDataTypes(DataType.TYPE_STEP_COUNT_DELTA).setDataTypes(DataType.TYPE_STEP_COUNT_CADENCE).setDataTypes(DataType.TYPE_LOCATION_SAMPLE)
            // 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.v("Inside", "Callback");
            Log.i(TAG, "Result: " + dataSourcesResult.getStatus().toString());
            Log.v("Len", dataSourcesResult.getDataSources().size() + "");
            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_CADENCE)
                  && mListener == null) {
                Log.i(TAG, "Data source for STEP found!  Registering.");
                registerFitnessDataListener(dataSource,
                    DataType.TYPE_STEP_COUNT_CADENCE);
              }
            }
          }
        });
    // [END find_data_sources]
  }

  private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
    // [START register_data_listener]
    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(
        mClient,
        new SensorRequest.Builder()
            .setDataSource(dataSource) // Optional but recommended for custom data sets.
            .setDataType(dataType) // 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.");
            }
          }
        });
    // [END register_data_listener]
  }

  private void buildFitnessClient() {
    // Create the Google API Client
    mClient = new GoogleApiClient.Builder(this)
        .addApi(Fitness.SENSORS_API).addApi(Fitness.RECORDING_API).addApi(Fitness.SESSIONS_API)
        .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE)).addScope(Fitness.SCOPE_ACTIVITY_READ_WRITE).addScope(Fitness.SCOPE_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.
                // Put application specific code here.
                findFitnessDataSources();
//                makeFitnessAPIRequest();
              }


              @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
                  GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(),
                      Home.this, 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");
                    authInProgress = true;
                    result.startResolutionForResult(Home.this,
                        REQUEST_OAUTH);
                  } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG,
                        "Exception while starting resolution activity", e);
                  }
                }
              }
            }
        )
        .build();
  }

  private void makeFitnessAPIRequest() {
    SensorRequest request = new SensorRequest.Builder().setDataType(DataType.TYPE_STEP_COUNT_DELTA)
        .setSamplingRate(1, TimeUnit.SECONDS).build();
    PendingResult<Status> reqResult = Fitness.SensorsApi.add(mClient, request, mListener);
  }

  @Override
  protected void onStart() {
    super.onStart();
    // Connect to the Fitness API
    Log.i(TAG, "Connecting...");
    mClient.connect();
  }

  @Override
  protected void onStop() {
    super.onStop();
    if (mClient.isConnected()) {
      mClient.disconnect();
    }
    Log.v("Inside", "Stop");
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_OAUTH) {
      authInProgress = false;
      if (resultCode == RESULT_OK) {
        // Make sure the app is not already connected or attempting to connect
        if (!mClient.isConnecting() && !mClient.isConnected()) {
          mClient.connect();
          Log.v("Inside", "connect");
        }
      }
    }
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean(AUTH_PENDING, authInProgress);
  }

  /**
   * Unregister the listener with the Sensors API.
   */
  private void unregisterFitnessDataListener() {
    if (mListener == null) {
      // This code only activates one listener at a time.  If there's no listener, there's
      // nothing to unregister.
      return;
    }

    // [START unregister_data_listener]
    // Waiting isn't actually necessary as the unregister call will complete regardless,
    // even if called from within onStop, but a callback can still be added in order to
    // inspect the results.
    Fitness.SensorsApi.remove(
        mClient,
        mListener)
        .setResultCallback(new ResultCallback<Status>() {
          @Override
          public void onResult(Status status) {
            if (status.isSuccess()) {
              Log.i(TAG, "Listener was removed!");
            } else {
              Log.i(TAG, "Listener was not removed.");
            }
          }
        });
    // [END unregister_data_listener]
  }

}

最佳答案

这对我有用,如果有人卡住,使用这个 ----

像这样初始化 FitnessClient 对象:

 private void buildFitnessClient() {
            if (mClient == null && checkPermissions()) {
                mClient = new GoogleApiClient.Builder(this)
                        .addApi(Fitness.SENSORS_API)
                        .addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
                        .addConnectionCallbacks(
                                new GoogleApiClient.ConnectionCallbacks() {
                                    @Override
                                    public void onConnected(Bundle bundle) {
                                        Log.i(TAG, "Connected!!!");
                                        // Now you can make calls to the Fitness APIs.
                                        findFitnessDataSources();
                                    }

现在定义你想要作为回调获取的数据类型,我们必须将其设置为 DataType.TYPE_STEP_COUNT_DELTA,如下所示:

 private void findFitnessDataSources() {
        // [START find_data_sources]
        // Note: Fitness.SensorsApi.findDataSources() requires the ACCESS_FINE_LOCATION permission.
        Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
                // At least one datatype must be specified.
                .setDataTypes(DataType.TYPE_STEP_COUNT_DELTA)

                        // Can specify whether data type is raw or derived.
                .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_DELTA)
                                && mListener == null) {
                            Log.i(TAG, "Data source for LOCATION_SAMPLE found!  Registering.");
                            registerFitnessDataListener(dataSource,
                                    DataType.TYPE_STEP_COUNT_DELTA);
                        }
                    }
                }
            });
    // [END find_data_sources]
}

现在使用传感器 API 为提供的数据源和数据类型注册一个监听器,如下所示:

private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
        // [START register_data_listener]
        mListener = new OnDataPointListener() {
            @Override
            public void onDataPoint(DataPoint dataPoint) {
                for (Field field : dataPoint.getDataType().getFields()) {
                    Value val = dataPoint.getValue(field);
//                    Value(TotalSteps);
//                     TotalSteps=val+TotalSteps;
                    Log.i(TAG, "Detected DataPoint field: " + field.getName());
                    Log.i(TAG, "Detected DataPoint value: " + val);
                }
            }
        };

        Fitness.SensorsApi.add(
                mClient,
                new SensorRequest.Builder()
                        .setDataSource(dataSource) // Optional but recommended for custom data sets.
                        .setDataType(dataType) // 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.");
                        }
                    }
                });
        // [END register_data_listener]
    }

也不要忘记注销您的监听器:

 private void unregisterFitnessDataListener() {
        if (mListener == null) {
            // This code only activates one listener at a time.  If there's no listener, there's
            // nothing to unregister.
            return;
        }

        // [START unregister_data_listener]
        // Waiting isn't actually necessary as the unregister call will complete regardless,
        // even if called from within onStop, but a callback can still be added in order to
        // inspect the results.
        Fitness.SensorsApi.remove(
                mClient,
                mListener)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        if (status.isSuccess()) {
                            Log.i(TAG, "Listener was removed!");
                        } else {
                            Log.i(TAG, "Listener was not removed.");
                        }
                    }
                });
        // [END unregister_data_listener]
    }

关于android - 如何使用 Google Fit Android API 获取步数的数据源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30156521/

有关android - 如何使用 Google Fit Android API 获取步数的数据源?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  5. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  6. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  7. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  8. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  9. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  10. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

随机推荐