为了向用户提供有用的服务,使应用程序具备上下文意识是最佳方法之一。尽管还有其他多种方法可以实现这一目标,如地理围栏、活动识别和其他位置服务,但Google最近推出了Awareness API。该API允许开发人员创建智能反应用户实际情况的应用程序。Awareness API结合了Places API、Locations API、Activity Recognition和Nearest API,并增加了对耳机状态和天气检测的支持。
在本教程中,您将学习关于Awareness API的知识,包括如何获取数据快照以及如何为符合应用程序目标的用户条件组合创建侦听器(称为fences,其名称来自地理围栏)。这对于各种应用程序都非常有用,比如基于位置的游戏可以向商店中的用户提供优惠券,并在检测到用户运动时启动音乐应用程序。您可以在GitHub上找到该示例应用程序的所有代码。
1.设置开发者控制台
在使用您的Android应用程序之前,您需要在Google API控制台中设置Google Play服务。如果您已经创建了一个项目,则可以跳过本节的第一步。如果还没有创建项目,您可以点击上方的链接并继续为您的应用程序创建一个新项目。
步骤1:建立专案
要创建一个新项目,请点击位于屏幕顶部中心的蓝色按钮,上面标有“创建项目”。
我们为您提供了一个对话框,以便询问您的项目名称。在本教程中,我创建了一个名为TutsPlusAwareness的项目。由于只能使用字母、数字、引号、连字符、空格和感叹号进行命名,因此对项目命名有一些限制。
点击Create后,页面的右下角将弹出一个对话框,指示正在创建项目。对话框消失后,您可以开始设置您的项目。您应该能够看到类似以下屏幕的界面。如果没有看到,请点击左上角的Google API徽标以转到API管理器屏幕。
步骤2:启用必要的API
在Google API概述页面上,点击搜索框,并输入Awareness API进行搜索。
在返回的结果中选择Awareness API,然后点击蓝色的“启用”按钮,以授权您的应用使用Awareness API。如果这是您第一次启用API,系统将提示您创建一组凭据。请继续执行本教程第3步的“凭据”页面。
除了使用Awareness API,您可能还需要启用其他API。如果您的应用使用了Awareness API中的Places功能,则需要启用Android版Google Places API。
如果您的应用使用信标,还需要启用附近消息API。
步骤3:建立Android API金钥
为了使用已启用的API,您需要为您的Android应用生成一个API密钥。请在您的Google项目凭据页面上,从顶部下拉菜单中选择意识度API,然后从第二个菜单中选择Android。

下一步,您将被引导至一个屏幕,在该屏幕上您可以输入应用程序的程序包名称和SHA1证书作为应用程序的签名密钥。如果您想在Linux或OS X上获取调试密钥的签名密钥,请在终端窗口中输入以下命令。
在Windows上,您可以将路径设置为debug.keystore文件的位置,并运行相同的命令:keytool -list -v -keystore [debug.keystore文件的位置] -alias androiddebugkey -storepass android -keypass android。当您单击“ 创建API密钥”按钮时,您将获得一个在Android应用程序中使用的API密钥。
2.设置Android项目
在创建并启用正确的API密钥后,您可以开始设置Android项目。在本教程中,我们将创建一个测试应用程序来学习API的使用。
为了展示Awareness API的全部功能,本教程将专注于使用一个简单的列表来呈现每个功能的使用。尽管我们不会详细讨论创建此列表的细节,但您可以在GitHub源代码中找到完整实现的教程。
步骤1:设定Play服务
首先,在您的build.gradle文件中,需要添加Play服务库。尽管可以包含所有Google Play服务,但最好只包含应用所需的软件包。
在这种情况下,您可以在项目中添加以下行来包含Awareness API。它位于ContextManager包中,并且需要将其作为依赖项节点的一部分。此外,请确保还包含了AppCompat库,因为该库将用于检查棉花糖及以上设备的权限。
在添加上述行之后,同步您的项目并打开您的项目的strings.xml文件。您需要将Google API控制台中的API密钥放入字符串值中。在添加API密钥后,您需要打开项目的AndroidManifest.xml文件。根据您使用的Awareness API功能,您需要包含应用程序所需的权限。如果您的应用程序使用了Awareness API中的信标、位置、地点或天气功能,则需要包括ACCESS_FINE_LOCATION权限。如果您需要使用活动识别功能,则还需添加ACTIVITY_RECOGNITION权限。请确保在AndroidManifest.xml文件中进行相应设置。接下来,我们需要添加以下权限到Android清单文件中:<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
public class MainActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGoogleApiClient = new GoogleApiClient.Builder(this) .addApi(Awareness.API) .build(); } }private boolean checkLocationPermission() { if (!hasLocationPermission()) { Log.e(Tuts+, Location permission not granted); requestLocationPermission(); return false; } }这段代码会触发系统对话框,询问用户是否愿意授予您的应用程序获取精确位置的权限。当用户响应后,您的应用程序可以通过
onRequestPermissionsResult()
回调接收结果,并做出相应的响应。@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_PERMISSION_RESULT_CODE: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //granted } else { Log.e("Tuts+", "Location permission denied."); } } }}
至此,您应该完成设置应用程序以使用Awareness API。
3.使用快照API
当您需要获取有关用户当前上下文的信息时,可以利用Awareness API的快照功能。该API会根据所发出的API调用类型来收集相关信息,并将其缓存以便在不同应用程序之间快速访问。
头戴式耳机
Play服务提供的新功能之一是通过Awareness API能够检测设备的耳机状态(插入或拔出)。要实现这一功能,只需调用Awareness API中的getHeadphoneState()方法,并从HeadphoneStateResult中读取HeadphoneState即可。
private void detectHeadphones() { Awareness.SnapshotApi.getHeadphoneState(mGoogleApiClient) .setResultCallback(new ResultCallback() { @Override public void onResult(@NonNull HeadphoneStateResult headphoneStateResult) { HeadphoneState headphoneState = headphoneStateResu位置
尽管以前可以将Awareness API作为Google Play服务的组件使用,但现在已对其位置功能进行了优化,以提高效率并减少电池消耗。您可以通过请求一次位置快照来获取位置信息,而无需使用传统的Location API并设置时间间隔来接收位置更新。
private void detectLocation() { if (!checkLocationPermission()) { return; } Awareness.SnapshotApi.getLocation(mGoogleApiClient) .setResultCallback(new ResultCallback() { @Override public void onResult(@NonNull LocationResult locationResult) { Location location = locationResult.getLocation(); Log.e(Tuts+, Latitude: + location.getLatitude() + , Longitude: + location.getLongitude()); Log.e(Tuts+, Provider: + location.getProvider() + , time: + location.getTime()); if (location.getAccuracy()由于可能存在某些数据不可用的情况,您在使用之前需要验证特定信息是否存在。运行此代码将会将所有可用数据输出到Android系统日志中。
尽管Awareness的位置信息是可用的,但我们无法获取到准确的纬度和经度。提供者快照时间为1468696704662,精确度为20.0。此外,海拔高度为0.0,速度为0.0。每个
Place
对象可能包含姓名,地址,电话号码,地点类型,用户评价,以及其他有用的信息。 您可以在确认用户已授予位置权限后,为该用户请求附近的地点。private void detectNearbyPlaces() { if( !checkLocationPermission() ) { return; } Awareness.SnapshotApi.getPlaces(mGoogleApiClient) .setResultCallback(new ResultCallback<PlacesResult>() { @Override public void onResult(@NonNull PlacesResult placesResult) { Place place; for( PlaceLikelihood placeLikelihood : placesResult.getPlaceLikelihoods() ) { place = placeLikelihood.getPlace(); Log.e("Tuts+", place.getName().toString() + "\n" + place.getAddress().toString() ); Log.e("Tuts+", "Rating: " + place.getRating() ); Log.e("Tuts+", "Likelihood that the user is here: " + placeLikelihood.getLikelihood() * 100 + "%"); } } });}
运行上述方法时,您应该在Android控制台中看到类似于以下内容的输出。 如果数字不可用,则返回
-1
。North Side Tavern, located at 12708 Lowell Blvd, Broomfield, CO 80020, USA, has received a rating of 4.7 according to E/Tuts+. The likelihood that the user is currently at this establishment is rated at a perfect score of 10.0. Similarly, the nearby Quilt Store at 12710 Lowell Blvd in Broomfield also has a rating of 4.3 according to E/Tuts+. Although not specified in the given information, it can be assumed that there is some level of likelihood associated with this store as well.通过使用此请求,您可以获取用户所在地区的温度,无论是以华氏度还是摄氏度表示。此外,您还可以获取到露点温度(即空气中水开始凝结成露水的温度)、湿度百分比和天气状况信息。
private void detectWeather() { if (!checkLocationPermission()) { return; } Awareness.SnapshotApi.getWeather(mGoogleApiClient) .setResultCallback(new ResultCallback() { @Override public void onResult(@NonNull WeatherResult weatherResult) { Weather weather = weatherResult.getWeather(); Log.e(Tuts+, Temperature: + weather.getTemperature(Weather.FAHRENHEIT)); Log.e(Tuts+,注意的一件事是,天气条件值被存储为整数。完整的条件值列表可以在“天气”对象中找到。```java final int CONDITION_UNKNOWN = 0; final int CONDITION_CLEAR = 1; final int CONDITION_CLOUDY = 2; final int CONDITION_FOGGY = 3; final int CONDITION_HAZY = 4; final int CONDITION_ICY = 5; final int CONDITION_RAINY = 6; final int CONDITION_SNOWY = 7; final int CONDITION_STORMY = 8; final int CONDITION_WINDY=9;活动
用户的活动将在他们与设备交互的方式中起很大的作用,检测到该活动将使您提供更流畅的用户体验。 ” ```
例如,如果您有健身应用程序,则可能希望检测用户何时跑步,以便开始记录Google Fit会话 ,或者如果您检测到用户仍在使用健身程序,则可能希望向其发送通知。白天太多时间。
通过使用Awareness API中的getDetectedActivity()方法调用,您可以获取可能活动的列表以及用户进行每个活动的时间。
private void detectActivity() { Awareness.SnapshotApi.getDetectedActivity(mGoogleApiClient) .setResultCallback(new ResultCallback() { @Override public void onResult(@NonNull DetectedActivityResult detectedActivityResult) { ActivityRecognitionResult result = detectedActivityResult.getActivityRecognitionResult(); Log.e(Tuts+, time: + result.getTime()); Log.e(Tuts+, activity: + result.getActivity()); } }); }DetectedActivity [type=STILL, confidence=100]的值可以映射到以下值:int IN_VEHICLE = 0; int ON_BICYCLE = 1; int ON_FOOT = 2; int STILL = 3; int UNKNOWN = 4; int TILTING = 5; int WALKING = 7; int RUNNING = 8; The variables are defined as follows: - IN_VEHICLE is assigned the value of 0. - ON_BICYCLE is assigned the value of 1. - ON_FOOT is assigned the value of 2. - STILL is assigned the value of 3. - UNKNOWN is assigned the value of4. - TILTING is assigned the value of5. - WALKING is assigned the value of7. - RUNNING is assigned the value of8.请注意,一旦您在Google API项目中注册了信标,就无法在不重置信标ID的情况下取消注册。这意味着如果您删除该项目,则需要使用制造商的应用程序重新配置信标。 对于Awareness API来说,名称空间必须与您用于Awareness API调用的Google项目匹配。上述提到的信标已经注册到一个个人测试的Google项目中,因此与本教程相关示例项目的名称空间(reflected-disk-355)不同。
在上面的屏幕截图中,您可以在“附件”下方找到一个项目。该附件的名称空间是反映磁盘-355(本教程中的示例项目)的命名空间是tutsplusawareness,并且类型就在附近。为了使用Awareness API检测附件,您需要使用此信息来创建自己的信标。
配置信标后,您可以返回代码。您需要创建一个 BeaconState.TypeFilter 对象 List,以便您的应用程序可以过滤掉与其无关的信标和附件。
以下是改写后的文案: ```java private static final List BEACON_TYPE_FILTERS = Arrays.asList( BeaconState.TypeFilter.with( // 替换这些值为您的信标数值 namespace, type ) ); ``` 如果您有理由相信用户在信标附近,可以从信标中请求符合上述过滤器要求的附件。这将要求棉花糖及更高版本上的用户具有位置权限。private void detectBeacons() { if (!checkLocationPermission()) { return; } Awareness.SnapshotApi.getBeaconState(mGoogleApiClient, BEACON_TYPE_FILTERS) .setResultCallback(new ResultCallback() { @Override public void onResult(@NonNull BeaconStateResult beaconStateResult) { if (!beaconStateResult.getStatus().isSuccess()) { Log.e(Test, Could not retrieve beacon state.); return; } // Rest of the codeE/Tuts+: Oh hi tuts+E/Tuts+: Portable Beacon info4.使用Fences API
尽管Snapshot API可以在特定时间获取有关用户上下文的信息,但是Fences API会在允许执行操作之前侦听要满足的特定条件。 Fences API已经针对提高电池和数据的使用效率进行了优化,以便对您的用户更加友好。
在创建围栏时,您可以检查五种类型的条件:
- 设备状况,例如拔出或插入耳机的用户
- 位置 ,类似于标准地理围栏
- 特定的BLE信标的存在
- 用户活动 ,例如跑步或驾驶
- 时间
目前,天气和地点的条件都不支持围栏。您可以利用任何可用的功能来创建围栏;然而,这个API真正方便的地方在于它允许您将逻辑运算应用于条件。您可以使用多个围栏,并且不能使用和、或来组合条件以满足应用程序的需求。
创建一个BroadcastReceiver
在开始创建围栏之前,您需要拥有一个代表应用程序将监听每个围栏的键值。为了完成本教程,您将构建一个围栏来监测用户何时坐在预设位置(例如家中)。
一旦定义了键KEY_SITTING_AT_HOME,就可以接收包含该键的广播Intent。public class FenceBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (TextUtils.equals(ACTION_FENCE, intent.getAction())) { FenceState fenceState = FenceState.extract(intent); if (TextUtils.equals(KEY_SITTING_AT_HOME, fenceState.getFenceKey())) { // Your code here } } } }AwarenessFence activityFence = DetectedActivityFence.during(DetectedActivityFence.STILL);
您将创建的第二个围栏将等待用户位于特定位置的范围内。 尽管此样本已设置了纬度和经度值,但是您将需要更改它们以匹配与您的位置相匹配的任何坐标以进行测试。
现在您已经有了两个栅栏,您可以通过使用`AwarenessFence.and`操作将它们组合在一起以创建第三个`AwarenessFence`。最后,您可以创建一个PendingIntent,该消息将广播到BroadcastReceiver并使用updateFences方法将其添加到Awareness API。Intent intent = new Intent(ACTION_FENCE); PendingIntent fencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); mFenceBroadcastReceiver = new FenceBroadcastReceiver(); registerReceiver(mFenceBroadcastReceiver, new IntentFilter(ACTION_FENCE));结论
在本教程中,您将了解到Awareness API的使用方法以及如何获取用户环境的实时信息。此外,您还将学习如何注册监听器以侦测用户上下文中的变化,并在满足特定条件时采取相应行动。
通过获取这些信息,您将能够进一步发展您的应用程序,并根据用户当前的位置、活动和其他有价值的因素,为他们提供更多令人惊叹的体验。
引用来源:https://code.tutsplus.com/tutorials/google-play-services-awareness-api--cms-25858 改写如下: 这段话翻译自 https://code.tutsplus.com/tutorials/google-play-services-awareness-api--cms-25858。
还木有评论哦,快来抢沙发吧~