我今天一整天都在与 Android Wear Message API 作斗争,终于接受了我需要一些帮助。
我的应用非常简单。移动部分由一个 MainActivity(除了显示“Hello world”什么都不做)和一个扩展 WearableListenerService 的服务组成。Wear 部分只是一个带有单个按钮的 MainActivity,并实现 MessageApi。 MessageListener.
想法很简单:按下 Wear 设备上的按钮,它会向移动设备发送消息。当 Mobile 收到消息时,它会显示一个 Toast,其中包含发件人的消息路径(例如 /mobile)。执行此操作后,移动设备应立即使用我的reply() 方法向 Wear 设备发送消息back。然后我想做的就是记录这条消息。
我可以完美地实现第一部分。按下 Button 时,Mobile 会弹出一个 Toast,上面写着“/mobile”。然而,答复似乎只是迷失在以太中。没有错误,但也没有消息。
有人可以帮我理解我做错了什么吗?我在下面粘贴了我的文件。
This是我正在关注的教程。干杯!
package org.thecosmicfrog.toastdroidmessageapitutorial;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.wearable.view.WatchViewStub;
import android.util.Log;
import android.view.View;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class MainActivity extends Activity implements MessageApi.MessageListener {
private final String LOG_TAG = MainActivity.class.getSimpleName();
private static final long CONNECTION_TIME_OUT_MS = 100;
private static final String MOBILE_PATH = "/mobile";
private GoogleApiClient googleApiClient;
private String nodeId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initGoogleApiClient();
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override
public void onLayoutInflated(WatchViewStub stub) {
initWidgets();
}
});
}
private void initGoogleApiClient() {
googleApiClient = getGoogleApiClient(this);
retrieveDeviceNode();
}
private GoogleApiClient getGoogleApiClient(Context context) {
return new GoogleApiClient.Builder(context)
.addApi(Wearable.API)
.build();
}
private void retrieveDeviceNode() {
new Thread(new Runnable() {
@Override
public void run() {
if (googleApiClient != null && !(googleApiClient.isConnected() || googleApiClient.isConnecting()))
googleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
NodeApi.GetConnectedNodesResult result =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
List<Node> nodes = result.getNodes();
if (nodes.size() > 0)
nodeId = nodes.get(0).getId();
Log.v(LOG_TAG, "Node ID of phone: " + nodeId);
googleApiClient.disconnect();
}
}).start();
}
private void initWidgets() {
findViewById(R.id.button_toast).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendToast();
}
});
}
private void sendToast() {
if (nodeId != null) {
new Thread(new Runnable() {
@Override
public void run() {
if (googleApiClient != null && !(googleApiClient.isConnected() || googleApiClient.isConnecting()))
googleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
Wearable.MessageApi.sendMessage(googleApiClient, nodeId, MOBILE_PATH, null).await();
googleApiClient.disconnect();
}
}).start();
}
}
@Override
public void onMessageReceived(MessageEvent messageEvent) {
Log.v(LOG_TAG, "In onMessageReceived()");
if (messageEvent.getPath().equals("/wear")) {
Log.v(LOG_TAG, "Success!");
}
}
}
package org.thecosmicfrog.toastdroidmessageapitutorial;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.util.concurrent.TimeUnit;
public class ListenerService extends WearableListenerService {
private final String LOG_TAG = ListenerService.class.getSimpleName();
private static GoogleApiClient googleApiClient;
private static final long CONNECTION_TIME_OUT_MS = 100;
private static final String WEAR_PATH = "/wear";
private String nodeId;
@Override
public void onMessageReceived(MessageEvent messageEvent) {
if (messageEvent.getPath().equals("/mobile")) {
nodeId = messageEvent.getSourceNodeId();
Log.v(LOG_TAG, "Node ID of watch: " + nodeId);
showToast(messageEvent.getPath());
reply(WEAR_PATH);
}
}
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
private void reply(final String path) {
googleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addApi(Wearable.API)
.build();
Log.v(LOG_TAG, "In reply()");
Log.v(LOG_TAG, "Path: " + path);
if (googleApiClient != null && !(googleApiClient.isConnected() || googleApiClient.isConnecting()))
googleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
Wearable.MessageApi.sendMessage(googleApiClient, nodeId, path, null).await();
googleApiClient.disconnect();
}
}
Mobile MainActivity 非常微不足道,因此为了清楚起见,我将其省略。
最佳答案
你永远不会调用 MessageApi.addListener()在您的 Wear Activity 中,因此您的 MessageListener 永远不会注册接收消息。您还应该调用 MessageApi.removeListener()当您的 Activity 被销毁时。
注意:这两种方法都需要连接 GoogleApiClient。如果您在整个 Activity 期间保持 GoogleApiClient 打开而不是尝试在 onDestroy()<>.removeListener()/disconnect,这可能会使逻辑更容易
关于java - 从可穿戴设备发送消息到手机,然后立即回复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27911579/
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我有这样的哈希trial_hash={"key1"=>1000,"key2"=>34,"key3"=>500,"key4"=>500,"key5"=>500,"key6"=>500}我按值降序排列:my_hash=trial_hash.sort_by{|k,v|v}.reverse我现在是这样理解的:[["key1",1000],["key4",500],["key5",500],["key6",500],["key3",500],["key2",34]]但我希望当值相同时按键的升序排序。我该怎么做?例如:上面的散列将以这种方式排序:[["key1",1000],["key3",500
我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=
我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt