使应用程序具有上下文意识是向用户提供有用服务的最佳方法之一。 有几种方法可以做到这一点,包括构建使用地理围栏和其他位置服务的应用程序。 本文重点介绍如何使用Google Play服务活动识别 API来确定用户是跑步,行走,乘车,骑自行车还是保持静止。
了解用户正在执行的活动可以使您满足应用程序的体验,例如,询问用户是否开始锻炼,以便您可以通过Google Fit跟踪它,或者阻止用户开车时发送通知。 本教程的源文件可以在GitHub上找到 。
1.项目设置
您需要做的第一件事是创建一个新的Android应用程序。 对于此示例应用程序,我将最小SDK设置为14并创建了一个默认的空Activity
。 一旦Android Studio创建了基本应用程序,请打开build.gradle文件,然后在“ dependencies
节点下导入Play服务(在撰写本文时,最新版本为8.4)。
compile 'com.google.android.gms:play-services:8.4.0'
接下来,创建一个新类,将其命名为ActivityRecognizedService
,并扩展IntentService
。 Google Play服务返回用户的活动后,会将其发送到此IntentService
。 这样,您就可以在用户忙碌的一天中在后台执行应用程序逻辑。
public class ActivityRecognizedService extends IntentService {
public ActivityRecognizedService() {
super("ActivityRecognizedService");
}
public ActivityRecognizedService(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
}
}
要完成设置,请打开AndroidManifest.xml 。 您需要声明ActivityRecognizedService
并为您的应用程序添加com.google.android.gms.permission.ACTIVITY_RECOGNITION
权限。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tutsplus.activityrecognition">
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ActivityRecognizedService" />
</application>
</manifest>
现在,您已经完成了应用程序的基本结构,可以继续进行下一步,以连接到Google Play服务并请求活动数据。
2.请求活动识别
为了使用Google Play服务,您首先需要连接到它们。 首先打开MainActivity.java并实现ConnectionCallbacks
和OnConnectionFailedListener
接口。 您还需要创建GoogleApiClient
类型的成员变量,以保留对API客户端的引用。
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
public GoogleApiClient mApiClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onConnected(@Nullable Bundle bundle) {
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
}
为GoogleApiClient
实现所需的接口后,您可以通过请求ActivityRecognition.API
并将您的侦听器与GoogleApiClient
实例相关联,来初始化客户端并通过onCreate()
连接到Google Play服务。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mApiClient = new GoogleApiClient.Builder(this)
.addApi(ActivityRecognition.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mApiClient.connect();
}
连接GoogleApiClient
实例后,将调用onConnected()
。 发生这种情况时,您需要创建一个PendingIntent
并将其传递给您先前创建的IntentService
,并将其传递给ActivityRecognitionApi
。 您还需要设置一个间隔,以间隔API检查用户活动的频率。 对于此示例应用程序,我们使用3000
或3秒的值,尽管在实际应用程序中,您可能希望减少检查频率以节省电量。
@Override
public void onConnected(@Nullable Bundle bundle) {
Intent intent = new Intent( this, ActivityRecognizedService.class );
PendingIntent pendingIntent = PendingIntent.getService( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT );
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates( mApiClient, 3000, pendingIntent );
}
此时,您的应用程序应尝试每三秒钟识别一次用户的活动,并将该数据发送到ActivityRecognizedService
。
3.处理活动识别
在ActivityRecognizedService
的onHandleIntent()
方法中,您要做的第一件事是验证接收到的Intent
包含活动识别数据。 如果是这样,那么您可以从Intent
提取ActivityRecognitionResult
,以查看您的用户可能正在执行哪些活动。 您可以通过在ActivityRecognitionResult
对象上调用getProbableActivities()
来检索可能的活动的列表。
@Override
protected void onHandleIntent(Intent intent) {
if(ActivityRecognitionResult.hasResult(intent)) {
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
handleDetectedActivities( result.getProbableActivities() );
}
}
对于此示例应用程序,您只需记录已检测到的每个活动,并通过在DetectedActivity
实例上调用getConfidence()
来显示Google Play服务对用户执行该活动的信心。 如果置信度是75或更高,则可以安全地假设用户正在执行该活动。 为了证明这一点,当您的应用程序检测到用户正在高度自信地行走时,您还会显示一条通知。
private void handleDetectedActivities(List<DetectedActivity> probableActivities) {
for( DetectedActivity activity : probableActivities ) {
switch( activity.getType() ) {
case DetectedActivity.IN_VEHICLE: {
Log.e( "ActivityRecogition", "In Vehicle: " + activity.getConfidence() );
break;
}
case DetectedActivity.ON_BICYCLE: {
Log.e( "ActivityRecogition", "On Bicycle: " + activity.getConfidence() );
break;
}
case DetectedActivity.ON_FOOT: {
Log.e( "ActivityRecogition", "On Foot: " + activity.getConfidence() );
break;
}
case DetectedActivity.RUNNING: {
Log.e( "ActivityRecogition", "Running: " + activity.getConfidence() );
break;
}
case DetectedActivity.STILL: {
Log.e( "ActivityRecogition", "Still: " + activity.getConfidence() );
break;
}
case DetectedActivity.TILTING: {
Log.e( "ActivityRecogition", "Tilting: " + activity.getConfidence() );
break;
}
case DetectedActivity.WALKING: {
Log.e( "ActivityRecogition", "Walking: " + activity.getConfidence() );
if( activity.getConfidence() >= 75 ) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText( "Are you walking?" );
builder.setSmallIcon( R.mipmap.ic_launcher );
builder.setContentTitle( getString( R.string.app_name ) );
NotificationManagerCompat.from(this).notify(0, builder.build());
}
break;
}
case DetectedActivity.UNKNOWN: {
Log.e( "ActivityRecogition", "Unknown: " + activity.getConfidence() );
break;
}
}
}
}
如果运行此应用程序,请运行,然后将设备插入计算机,您应该在开发控制台中看到类似于以下内容的日志。
E/ActivityRecogition: On Foot: 92
E/ActivityRecogition: Running: 87
E/ActivityRecogition: On Bicycle: 8
E/ActivityRecogition: Walking: 5
如果您去散步,您应该收到一条通知,询问您是否在散步。 如果您有锻炼应用程序,那么这将是向用户提供使他们能够开始跟踪其锻炼的动作的绝佳机会。
结论
Google Play服务可让您轻松确定用户的当前活动。 这对于使您的应用程序具有上下文感知能力和对您的用户而言非常有用,这对涉及的每个人都非常有用。 仅需几行代码,您就可以使应用程序更智能。