Android WearListenerService OnData改变了奇怪的行为
我想在Android Wear和掌上电脑之间进行双向数据传输。 除了在掌上电脑上改变触发数据外,一切似乎都很好。只有当我插入\拔出USB电缆并连接到电脑时,它才会触发。 所以我不明白为什么会这样 这是我的密码: 手持设备上的WearListenerService:Android WearListenerService OnData改变了奇怪的行为,android,wear-os,android-wear-data-api,Android,Wear Os,Android Wear Data Api,我想在Android Wear和掌上电脑之间进行双向数据传输。 除了在掌上电脑上改变触发数据外,一切似乎都很好。只有当我插入\拔出USB电缆并连接到电脑时,它才会触发。 所以我不明白为什么会这样 这是我的密码: 手持设备上的WearListenerService: import android.content.Intent; import android.os.Bundle; import android.support.v4.content.LocalBroadcastManager; im
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.util.List;
import ru.orangesoftware.financisto.db.DatabaseAdapter;
import ru.orangesoftware.financisto.model.Category;
import ru.orangesoftware.financisto.model.CategoryTree;
import ru.orangesoftware.financisto.utils.Log;
public class WearService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
{
private static final String WEARABLE_DATA_PATH = "/wearable_data";
private static final String HANDHELD_DATA_PATH = "/handheld_data";
private SendToDataLayerThread s;
GoogleApiClient googleClient;
private DatabaseAdapter db;
@Override
public void onCreate()
{
super.onCreate();
Log.d("WearService Created");
db = new DatabaseAdapter(this);
db.open();
initGoogleApiClient();
}
@Override
public void onDataChanged(DataEventBuffer dataEvents)
{
Log.d("In dataChanged");
DataMap dataMap;
for (DataEvent event : dataEvents)
{
// Check the data type
if (event.getType() == DataEvent.TYPE_CHANGED)
{
// Check the data path
String path = event.getDataItem().getUri().getPath();
if (path.equals(HANDHELD_DATA_PATH))
{
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Log.v("Path phone: " + path);
Log.v("DataMap received from watch: " + dataMap);
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("time", System.currentTimeMillis());
messageIntent.putExtra("DataMap", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
// Create a DataMap object and send it to the data layer
dataMap = new DataMap();
dataMap.putString("Pong", "Pong" + String.valueOf(System.currentTimeMillis()));
dataMap.putLong("time", System.currentTimeMillis());
//Requires a new thread to avoid blocking the UI
s = new SendToDataLayerThread(WEARABLE_DATA_PATH, dataMap);
s.start();
}
}
}
}
private void initGoogleApiClient()
{
// Build a new GoogleApiClient for the the Wearable API
Log.d("Initialaizing GoogleClient");
if (googleClient == null)
{
googleClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
if (!googleClient.isConnected())
{
Log.d("Tring to connect to GoogleApi...");
googleClient.connect();
}
Log.d("Google Client ID = " + googleClient.toString());
}
// Disconnect from the data layer when the Activity stops
@Override
public void onDestroy()
{
super.onDestroy();
Log.d("WearService: onDestroy");
if (null != googleClient && googleClient.isConnected())
{
googleClient.disconnect();
}
if (db != null)
{
db.close();
}
}
@Override
public void onConnected(Bundle bundle)
{
Log.d("onConnected entered");
Log.d("GoogleAPI now status:" + googleClient.isConnected());
}
@Override
public void onConnectionSuspended(int i)
{
}
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.e("Connection to google api has failed. " + result.getErrorMessage());
}
class SendToDataLayerThread extends Thread
{
String path;
DataMap dataMap;
// Constructor for sending data objects to the data layer
SendToDataLayerThread(String p, DataMap data)
{
path = p;
dataMap = data;
}
public void run()
{
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleClient).await();
for (Node node : nodes.getNodes())
{
// Construct a DataRequest and send over the data layer
PutDataMapRequest putDMR = PutDataMapRequest.create(path);
putDMR.getDataMap().putAll(dataMap);
PutDataRequest request = putDMR.asPutDataRequest();
DataApi.DataItemResult result = Wearable.DataApi.putDataItem(googleClient, request).await();
if (result.getStatus().isSuccess())
{
Log.v("DataMap: " + dataMap + " sent to: " + node.getDisplayName() + "; path=" + path);
} else
{
// Log an error
Log.v("ERROR: failed to send DataMap");
}
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest package="ru.orangesoftware.financisto"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.hardware.type.watch"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@android:style/Theme.DeviceDefault">
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<activity
android:name=".MainWearActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name="ru.orangesoftware.financisto.ListenerService"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER"/>
</intent-filter>
</service>
</application>
</manifest>
11-15 12:24:25.301 2460-2460/ru.orangesoftware.financisto D/FinancistoWear: onStartCommand: Service was started.
11-15 12:24:25.377 2460-2460/ru.orangesoftware.financisto V/FinancistoWear: DataMap: {time=1447565065308, ping=ping1447565065306} sent to: Tolive GN3
11-15 12:24:25.379 2460-3309/ru.orangesoftware.financisto D/FinancistoWear: In dataChanged
11-15 12:24:25.379 2460-3309/ru.orangesoftware.financisto D/FinancistoWear: DataChanged: path = /handheld_data
佩戴式耳机佩戴时的服务:
import android.content.Intent;
import android.os.Bundle;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
public class ListenerService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
{
private static final String WEARABLE_DATA_PATH = "/wearable_data";
private static final String HANDHELD_DATA_PATH = "/handheld_data";
GoogleApiClient googleClient;
private SendToDataLayerThread s;
@Override
public void onDataChanged(DataEventBuffer dataEvents)
{
Log.d("In dataChanged");
DataMap dataMap;
for (DataEvent event : dataEvents)
{
// Check the data type
if (event.getType() == DataEvent.TYPE_CHANGED)
{
// Check the data path
String path = event.getDataItem().getUri().getPath();
Log.d("DataChanged: " + "path = " + path);
if (path.equals(WEARABLE_DATA_PATH))
{
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Log.d("DataChanged: " + "dataMap received on watch: " + dataMap);
}
}
}
}
private void initGoogleApiClient()
{
if (googleClient == null)
{
Log.d("Building google client id...");
googleClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Log.d("Google client id = " + googleClient.toString());
}
if (!googleClient.isConnected())
{
googleClient.connect();
}
Log.d("Google Client ID = " + googleClient.toString());
}
// Placeholders for required connection callbacks
@Override
public void onConnectionSuspended(int cause)
{
}
@Override
public void onConnected(Bundle connectionHint)
{
Log.v("OnConnected entered");
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
{
}
// Connect to the data layer when the Activity starts
@Override
public void onCreate()
{
super.onCreate();
initGoogleApiClient();
}
// Disconnect from the data layer when the Activity stops
@Override
public void onDestroy()
{
if (null != googleClient && googleClient.isConnected())
{
Log.d("onDestroy: Disconnecting googleClient");
googleClient.disconnect();
}
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startid)
{
Log.d("onStartCommand: Service was started.");
// Create a DataMap object and send it to the data layer
DataMap dataMap = new DataMap();
dataMap.putString("ping", "ping" + String.valueOf(System.currentTimeMillis()));
dataMap.putLong("time", System.currentTimeMillis());
//Requires a new thread to avoid blocking the UI
s = new SendToDataLayerThread(HANDHELD_DATA_PATH, dataMap);
s.start();
return super.onStartCommand(intent, flags, startid);
}
class SendToDataLayerThread extends Thread
{
String path;
DataMap dataMap;
// Constructor for sending data objects to the data layer
SendToDataLayerThread(String p, DataMap data)
{
path = p;
dataMap = data;
}
public void run()
{
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleClient).await();
for (Node node : nodes.getNodes())
{
final Node node2 = node;
// Construct a DataRequest and send over the data layer
PutDataMapRequest putDMR = PutDataMapRequest.create(path);
putDMR.getDataMap().putAll(dataMap);
PutDataRequest request = putDMR.asPutDataRequest();
PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi.putDataItem(googleClient, request);
pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult>()
{
@Override
public void onResult(DataApi.DataItemResult dataItemResult)
{
if (dataItemResult.getStatus().isSuccess())
{
Log.v("DataMap: " + dataMap + " sent to: " + node2.getDisplayName());
} else
{
// Log an error
Log.v("ERROR: failed to send DataMap");
}
}
});
}
}
}
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
repositories {
maven { url "http://repo.commonsware.com.s3.amazonaws.com" }
maven { url "https://repository-achartengine.forge.cloudbees.com/snapshot/" }
mavenCentral()
}
android {
compileSdkVersion 22
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "ru.orangesoftware.financisto"
minSdkVersion 19
targetSdkVersion 22
versionCode 92
versionName "1.6.8"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
}
}
def googlePlayVersion = '8.3.0'
dependencies {
compile "com.google.android.gms:play-services-base:$googlePlayVersion"
compile "com.google.android.gms:play-services-drive:$googlePlayVersion"
compile "com.google.android.gms:play-services-wearable:$googlePlayVersion"
compile files('libs/dropbox-android-sdk-1.6.1/dropbox-android-sdk-1.6.1.jar')
compile files('libs/google-rfc-2445/rfc2445-no-joda.jar')
compile 'com.google.code.gson:gson:2.3'
compile 'com.commonsware.cwac:wakeful:1.0.1'
compile 'org.achartengine:achartengine:1.2.0'
compile 'net.sf.trove4j:trove4j:3.0.3'
compile 'com.wdullaer:materialdatetimepicker:2.0.0'
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "ru.orangesoftware.financisto"
minSdkVersion 20
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
def googlePlayVersion = '8.3.0'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.android.support:wearable:1.3.0'
compile "com.google.android.gms:play-services-wearable:$googlePlayVersion"
}
11-15 12:20:20.616 29043-29043/? D/Financisto: WearService Created [WearService.onCreate:44]
11-15 12:20:20.616 29043-29043/? D/Financisto: Initialaizing GoogleClient [WearService.initGoogleApiClient:94]
11-15 12:20:20.636 29043-29043/? D/Financisto: Tring to connect to GoogleApi... [WearService.initGoogleApiClient:107]
11-15 12:20:20.636 29043-29043/? D/Financisto: Google Client ID = com.google.android.gms.internal.zzmg@4344d5c0 [WearService.initGoogleApiClient:113]
11-15 12:20:21.016 29043-29043/ru.orangesoftware.financisto D/Financisto: onConnected entered [WearService.onConnected:139]
11-15 12:20:21.016 29043-29043/ru.orangesoftware.financisto D/Financisto: GoogleAPI now status:true [WearService.onConnected:140]
-------now I send data from watch and unplug usb cable after 30 seconds
11-15 12:24:31.986 29043-29091/? D/Financisto: In dataChanged [WearService.onDataChanged:54]
11-15 12:24:31.986 29043-29091/? V/Financisto: Path phone: /handheld_data [WearService.onDataChanged:68]
11-15 12:24:31.986 29043-29091/? V/Financisto: DataMap received from watch: {time=1447565065308, ping=ping1447565065306} [WearService.onDataChanged:69]
11-15 12:24:32.036 29043-29091/? D/Financisto: In dataChanged [WearService.onDataChanged:54]
11-15 12:24:32.046 29043-1493/? V/Financisto: DataMap: {Pong=Pong1447565071992, time=1447565071992} sent to: Gear 2 76A1; path=/wearable_data [SendToDataLayerThread.run:179]
渐变磨损:
import android.content.Intent;
import android.os.Bundle;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
public class ListenerService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
{
private static final String WEARABLE_DATA_PATH = "/wearable_data";
private static final String HANDHELD_DATA_PATH = "/handheld_data";
GoogleApiClient googleClient;
private SendToDataLayerThread s;
@Override
public void onDataChanged(DataEventBuffer dataEvents)
{
Log.d("In dataChanged");
DataMap dataMap;
for (DataEvent event : dataEvents)
{
// Check the data type
if (event.getType() == DataEvent.TYPE_CHANGED)
{
// Check the data path
String path = event.getDataItem().getUri().getPath();
Log.d("DataChanged: " + "path = " + path);
if (path.equals(WEARABLE_DATA_PATH))
{
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Log.d("DataChanged: " + "dataMap received on watch: " + dataMap);
}
}
}
}
private void initGoogleApiClient()
{
if (googleClient == null)
{
Log.d("Building google client id...");
googleClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Log.d("Google client id = " + googleClient.toString());
}
if (!googleClient.isConnected())
{
googleClient.connect();
}
Log.d("Google Client ID = " + googleClient.toString());
}
// Placeholders for required connection callbacks
@Override
public void onConnectionSuspended(int cause)
{
}
@Override
public void onConnected(Bundle connectionHint)
{
Log.v("OnConnected entered");
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
{
}
// Connect to the data layer when the Activity starts
@Override
public void onCreate()
{
super.onCreate();
initGoogleApiClient();
}
// Disconnect from the data layer when the Activity stops
@Override
public void onDestroy()
{
if (null != googleClient && googleClient.isConnected())
{
Log.d("onDestroy: Disconnecting googleClient");
googleClient.disconnect();
}
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startid)
{
Log.d("onStartCommand: Service was started.");
// Create a DataMap object and send it to the data layer
DataMap dataMap = new DataMap();
dataMap.putString("ping", "ping" + String.valueOf(System.currentTimeMillis()));
dataMap.putLong("time", System.currentTimeMillis());
//Requires a new thread to avoid blocking the UI
s = new SendToDataLayerThread(HANDHELD_DATA_PATH, dataMap);
s.start();
return super.onStartCommand(intent, flags, startid);
}
class SendToDataLayerThread extends Thread
{
String path;
DataMap dataMap;
// Constructor for sending data objects to the data layer
SendToDataLayerThread(String p, DataMap data)
{
path = p;
dataMap = data;
}
public void run()
{
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleClient).await();
for (Node node : nodes.getNodes())
{
final Node node2 = node;
// Construct a DataRequest and send over the data layer
PutDataMapRequest putDMR = PutDataMapRequest.create(path);
putDMR.getDataMap().putAll(dataMap);
PutDataRequest request = putDMR.asPutDataRequest();
PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi.putDataItem(googleClient, request);
pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult>()
{
@Override
public void onResult(DataApi.DataItemResult dataItemResult)
{
if (dataItemResult.getStatus().isSuccess())
{
Log.v("DataMap: " + dataMap + " sent to: " + node2.getDisplayName());
} else
{
// Log an error
Log.v("ERROR: failed to send DataMap");
}
}
});
}
}
}
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
repositories {
maven { url "http://repo.commonsware.com.s3.amazonaws.com" }
maven { url "https://repository-achartengine.forge.cloudbees.com/snapshot/" }
mavenCentral()
}
android {
compileSdkVersion 22
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "ru.orangesoftware.financisto"
minSdkVersion 19
targetSdkVersion 22
versionCode 92
versionName "1.6.8"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
}
}
def googlePlayVersion = '8.3.0'
dependencies {
compile "com.google.android.gms:play-services-base:$googlePlayVersion"
compile "com.google.android.gms:play-services-drive:$googlePlayVersion"
compile "com.google.android.gms:play-services-wearable:$googlePlayVersion"
compile files('libs/dropbox-android-sdk-1.6.1/dropbox-android-sdk-1.6.1.jar')
compile files('libs/google-rfc-2445/rfc2445-no-joda.jar')
compile 'com.google.code.gson:gson:2.3'
compile 'com.commonsware.cwac:wakeful:1.0.1'
compile 'org.achartengine:achartengine:1.2.0'
compile 'net.sf.trove4j:trove4j:3.0.3'
compile 'com.wdullaer:materialdatetimepicker:2.0.0'
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "ru.orangesoftware.financisto"
minSdkVersion 20
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
def googlePlayVersion = '8.3.0'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.android.support:wearable:1.3.0'
compile "com.google.android.gms:play-services-wearable:$googlePlayVersion"
}
11-15 12:20:20.616 29043-29043/? D/Financisto: WearService Created [WearService.onCreate:44]
11-15 12:20:20.616 29043-29043/? D/Financisto: Initialaizing GoogleClient [WearService.initGoogleApiClient:94]
11-15 12:20:20.636 29043-29043/? D/Financisto: Tring to connect to GoogleApi... [WearService.initGoogleApiClient:107]
11-15 12:20:20.636 29043-29043/? D/Financisto: Google Client ID = com.google.android.gms.internal.zzmg@4344d5c0 [WearService.initGoogleApiClient:113]
11-15 12:20:21.016 29043-29043/ru.orangesoftware.financisto D/Financisto: onConnected entered [WearService.onConnected:139]
11-15 12:20:21.016 29043-29043/ru.orangesoftware.financisto D/Financisto: GoogleAPI now status:true [WearService.onConnected:140]
-------now I send data from watch and unplug usb cable after 30 seconds
11-15 12:24:31.986 29043-29091/? D/Financisto: In dataChanged [WearService.onDataChanged:54]
11-15 12:24:31.986 29043-29091/? V/Financisto: Path phone: /handheld_data [WearService.onDataChanged:68]
11-15 12:24:31.986 29043-29091/? V/Financisto: DataMap received from watch: {time=1447565065308, ping=ping1447565065306} [WearService.onDataChanged:69]
11-15 12:24:32.036 29043-29091/? D/Financisto: In dataChanged [WearService.onDataChanged:54]
11-15 12:24:32.046 29043-1493/? V/Financisto: DataMap: {Pong=Pong1447565071992, time=1447565071992} sent to: Gear 2 76A1; path=/wearable_data [SendToDataLayerThread.run:179]
在应用程序启动后登录掌上电脑:
import android.content.Intent;
import android.os.Bundle;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
public class ListenerService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
{
private static final String WEARABLE_DATA_PATH = "/wearable_data";
private static final String HANDHELD_DATA_PATH = "/handheld_data";
GoogleApiClient googleClient;
private SendToDataLayerThread s;
@Override
public void onDataChanged(DataEventBuffer dataEvents)
{
Log.d("In dataChanged");
DataMap dataMap;
for (DataEvent event : dataEvents)
{
// Check the data type
if (event.getType() == DataEvent.TYPE_CHANGED)
{
// Check the data path
String path = event.getDataItem().getUri().getPath();
Log.d("DataChanged: " + "path = " + path);
if (path.equals(WEARABLE_DATA_PATH))
{
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Log.d("DataChanged: " + "dataMap received on watch: " + dataMap);
}
}
}
}
private void initGoogleApiClient()
{
if (googleClient == null)
{
Log.d("Building google client id...");
googleClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Log.d("Google client id = " + googleClient.toString());
}
if (!googleClient.isConnected())
{
googleClient.connect();
}
Log.d("Google Client ID = " + googleClient.toString());
}
// Placeholders for required connection callbacks
@Override
public void onConnectionSuspended(int cause)
{
}
@Override
public void onConnected(Bundle connectionHint)
{
Log.v("OnConnected entered");
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
{
}
// Connect to the data layer when the Activity starts
@Override
public void onCreate()
{
super.onCreate();
initGoogleApiClient();
}
// Disconnect from the data layer when the Activity stops
@Override
public void onDestroy()
{
if (null != googleClient && googleClient.isConnected())
{
Log.d("onDestroy: Disconnecting googleClient");
googleClient.disconnect();
}
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startid)
{
Log.d("onStartCommand: Service was started.");
// Create a DataMap object and send it to the data layer
DataMap dataMap = new DataMap();
dataMap.putString("ping", "ping" + String.valueOf(System.currentTimeMillis()));
dataMap.putLong("time", System.currentTimeMillis());
//Requires a new thread to avoid blocking the UI
s = new SendToDataLayerThread(HANDHELD_DATA_PATH, dataMap);
s.start();
return super.onStartCommand(intent, flags, startid);
}
class SendToDataLayerThread extends Thread
{
String path;
DataMap dataMap;
// Constructor for sending data objects to the data layer
SendToDataLayerThread(String p, DataMap data)
{
path = p;
dataMap = data;
}
public void run()
{
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleClient).await();
for (Node node : nodes.getNodes())
{
final Node node2 = node;
// Construct a DataRequest and send over the data layer
PutDataMapRequest putDMR = PutDataMapRequest.create(path);
putDMR.getDataMap().putAll(dataMap);
PutDataRequest request = putDMR.asPutDataRequest();
PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi.putDataItem(googleClient, request);
pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult>()
{
@Override
public void onResult(DataApi.DataItemResult dataItemResult)
{
if (dataItemResult.getStatus().isSuccess())
{
Log.v("DataMap: " + dataMap + " sent to: " + node2.getDisplayName());
} else
{
// Log an error
Log.v("ERROR: failed to send DataMap");
}
}
});
}
}
}
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
repositories {
maven { url "http://repo.commonsware.com.s3.amazonaws.com" }
maven { url "https://repository-achartengine.forge.cloudbees.com/snapshot/" }
mavenCentral()
}
android {
compileSdkVersion 22
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "ru.orangesoftware.financisto"
minSdkVersion 19
targetSdkVersion 22
versionCode 92
versionName "1.6.8"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
}
}
def googlePlayVersion = '8.3.0'
dependencies {
compile "com.google.android.gms:play-services-base:$googlePlayVersion"
compile "com.google.android.gms:play-services-drive:$googlePlayVersion"
compile "com.google.android.gms:play-services-wearable:$googlePlayVersion"
compile files('libs/dropbox-android-sdk-1.6.1/dropbox-android-sdk-1.6.1.jar')
compile files('libs/google-rfc-2445/rfc2445-no-joda.jar')
compile 'com.google.code.gson:gson:2.3'
compile 'com.commonsware.cwac:wakeful:1.0.1'
compile 'org.achartengine:achartengine:1.2.0'
compile 'net.sf.trove4j:trove4j:3.0.3'
compile 'com.wdullaer:materialdatetimepicker:2.0.0'
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "ru.orangesoftware.financisto"
minSdkVersion 20
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
def googlePlayVersion = '8.3.0'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.android.support:wearable:1.3.0'
compile "com.google.android.gms:play-services-wearable:$googlePlayVersion"
}
11-15 12:20:20.616 29043-29043/? D/Financisto: WearService Created [WearService.onCreate:44]
11-15 12:20:20.616 29043-29043/? D/Financisto: Initialaizing GoogleClient [WearService.initGoogleApiClient:94]
11-15 12:20:20.636 29043-29043/? D/Financisto: Tring to connect to GoogleApi... [WearService.initGoogleApiClient:107]
11-15 12:20:20.636 29043-29043/? D/Financisto: Google Client ID = com.google.android.gms.internal.zzmg@4344d5c0 [WearService.initGoogleApiClient:113]
11-15 12:20:21.016 29043-29043/ru.orangesoftware.financisto D/Financisto: onConnected entered [WearService.onConnected:139]
11-15 12:20:21.016 29043-29043/ru.orangesoftware.financisto D/Financisto: GoogleAPI now status:true [WearService.onConnected:140]
-------now I send data from watch and unplug usb cable after 30 seconds
11-15 12:24:31.986 29043-29091/? D/Financisto: In dataChanged [WearService.onDataChanged:54]
11-15 12:24:31.986 29043-29091/? V/Financisto: Path phone: /handheld_data [WearService.onDataChanged:68]
11-15 12:24:31.986 29043-29091/? V/Financisto: DataMap received from watch: {time=1447565065308, ping=ping1447565065306} [WearService.onDataChanged:69]
11-15 12:24:32.036 29043-29091/? D/Financisto: In dataChanged [WearService.onDataChanged:54]
11-15 12:24:32.046 29043-1493/? V/Financisto: DataMap: {Pong=Pong1447565071992, time=1447565071992} sent to: Gear 2 76A1; path=/wearable_data [SendToDataLayerThread.run:179]
在应用程序启动和数据发送后登录:
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.util.List;
import ru.orangesoftware.financisto.db.DatabaseAdapter;
import ru.orangesoftware.financisto.model.Category;
import ru.orangesoftware.financisto.model.CategoryTree;
import ru.orangesoftware.financisto.utils.Log;
public class WearService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
{
private static final String WEARABLE_DATA_PATH = "/wearable_data";
private static final String HANDHELD_DATA_PATH = "/handheld_data";
private SendToDataLayerThread s;
GoogleApiClient googleClient;
private DatabaseAdapter db;
@Override
public void onCreate()
{
super.onCreate();
Log.d("WearService Created");
db = new DatabaseAdapter(this);
db.open();
initGoogleApiClient();
}
@Override
public void onDataChanged(DataEventBuffer dataEvents)
{
Log.d("In dataChanged");
DataMap dataMap;
for (DataEvent event : dataEvents)
{
// Check the data type
if (event.getType() == DataEvent.TYPE_CHANGED)
{
// Check the data path
String path = event.getDataItem().getUri().getPath();
if (path.equals(HANDHELD_DATA_PATH))
{
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Log.v("Path phone: " + path);
Log.v("DataMap received from watch: " + dataMap);
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("time", System.currentTimeMillis());
messageIntent.putExtra("DataMap", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
// Create a DataMap object and send it to the data layer
dataMap = new DataMap();
dataMap.putString("Pong", "Pong" + String.valueOf(System.currentTimeMillis()));
dataMap.putLong("time", System.currentTimeMillis());
//Requires a new thread to avoid blocking the UI
s = new SendToDataLayerThread(WEARABLE_DATA_PATH, dataMap);
s.start();
}
}
}
}
private void initGoogleApiClient()
{
// Build a new GoogleApiClient for the the Wearable API
Log.d("Initialaizing GoogleClient");
if (googleClient == null)
{
googleClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
if (!googleClient.isConnected())
{
Log.d("Tring to connect to GoogleApi...");
googleClient.connect();
}
Log.d("Google Client ID = " + googleClient.toString());
}
// Disconnect from the data layer when the Activity stops
@Override
public void onDestroy()
{
super.onDestroy();
Log.d("WearService: onDestroy");
if (null != googleClient && googleClient.isConnected())
{
googleClient.disconnect();
}
if (db != null)
{
db.close();
}
}
@Override
public void onConnected(Bundle bundle)
{
Log.d("onConnected entered");
Log.d("GoogleAPI now status:" + googleClient.isConnected());
}
@Override
public void onConnectionSuspended(int i)
{
}
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.e("Connection to google api has failed. " + result.getErrorMessage());
}
class SendToDataLayerThread extends Thread
{
String path;
DataMap dataMap;
// Constructor for sending data objects to the data layer
SendToDataLayerThread(String p, DataMap data)
{
path = p;
dataMap = data;
}
public void run()
{
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleClient).await();
for (Node node : nodes.getNodes())
{
// Construct a DataRequest and send over the data layer
PutDataMapRequest putDMR = PutDataMapRequest.create(path);
putDMR.getDataMap().putAll(dataMap);
PutDataRequest request = putDMR.asPutDataRequest();
DataApi.DataItemResult result = Wearable.DataApi.putDataItem(googleClient, request).await();
if (result.getStatus().isSuccess())
{
Log.v("DataMap: " + dataMap + " sent to: " + node.getDisplayName() + "; path=" + path);
} else
{
// Log an error
Log.v("ERROR: failed to send DataMap");
}
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest package="ru.orangesoftware.financisto"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.hardware.type.watch"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@android:style/Theme.DeviceDefault">
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<activity
android:name=".MainWearActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name="ru.orangesoftware.financisto.ListenerService"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER"/>
</intent-filter>
</service>
</application>
</manifest>
11-15 12:24:25.301 2460-2460/ru.orangesoftware.financisto D/FinancistoWear: onStartCommand: Service was started.
11-15 12:24:25.377 2460-2460/ru.orangesoftware.financisto V/FinancistoWear: DataMap: {time=1447565065308, ping=ping1447565065306} sent to: Tolive GN3
11-15 12:24:25.379 2460-3309/ru.orangesoftware.financisto D/FinancistoWear: In dataChanged
11-15 12:24:25.379 2460-3309/ru.orangesoftware.financisto D/FinancistoWear: DataChanged: path = /handheld_data
请告诉我,我做错了什么
解决方案
我重写了SendtoAtatalayerthread。现在它是一个常规类,没有扩展线程,DataRequest变得很紧急:
class SendToDataLayerThread
{
String path;
DataMap dataMap;
// Constructor for sending data objects to the data layer
SendToDataLayerThread(String p, DataMap data)
{
path = p;
dataMap = data;
}
public void run()
{
//NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleClient);
PendingResult<NodeApi.GetConnectedNodesResult> nodes = Wearable.NodeApi.getConnectedNodes(googleClient);
nodes.setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>()
{
@Override
public void onResult(NodeApi.GetConnectedNodesResult getConnectedNodesResult)
{
for (Node node : getConnectedNodesResult.getNodes())
{
final Node node2 = node;
// Construct a DataRequest and send over the data layer
PutDataMapRequest putDMR = PutDataMapRequest.create(path);
putDMR.getDataMap().putAll(dataMap);
PutDataRequest request = putDMR.asPutDataRequest();
request.setUrgent();
PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi.putDataItem(googleClient, request);
pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult>()
{
@Override
public void onResult(DataApi.DataItemResult dataItemResult)
{
if (dataItemResult.getStatus().isSuccess())
{
Log.v("DataMap: " + dataMap + " sent to: " + node2.getDisplayName());
} else
{
// Log an error
Log.v("ERROR: failed to send DataMap");
}
}
});
}
}
});
}
}
类SendToDataLayerThread
{
字符串路径;
数据地图;
//用于将数据对象发送到数据层的构造函数
SendToDataLayerThread(字符串p,数据映射数据)
{
path=p;
数据地图=数据;
}
公开募捐
{
//NodeApi.getConnectedNodeResult nodes=可穿戴的.NodeApi.getConnectedNodes(谷歌客户端);
Pendingreult节点=可穿戴的.NodeApi.getConnectedNodes(谷歌客户端);
setResultCallback(新的ResultCallback()
{
@凌驾
公共void onResult(NodeApi.GetConnectedNodesResult GetConnectedNodesResult)
{
对于(节点:GetConnectedNodeResult.getNodes())
{
最终节点node2=节点;
//构造DataRequest并通过数据层发送
PutDataMapRequest putDMR=PutDataMapRequest.create(路径);
putDMR.getDataMap().putAll(dataMap);
PutDataRequest=putDMR.asPutDataRequest();
request.setUrgent();
Pendingreult Pendingreult=Wearable.DataApi.putDataItem(谷歌客户端,请求);
Pendingreult.setResultCallback(新的ResultCallback()
{
@凌驾
public void onResult(DataApi.DataItemResult DataItemResult)
{
if(dataItemResult.getStatus().isSuccess())
{
Log.v(“DataMap:+DataMap+”发送到:“+node2.getDisplayName()”);
}否则
{
//记录错误
Log.v(“错误:无法发送数据映射”);
}
}
});
}
}
});
}
}
谢谢你的帮助 根据:
使用GooglePlayServices8.3,我们更新了DataApi,以便在同步数据项时考虑到紧迫性。现在,可以向数据项添加优先级,以确定何时应同步该数据项。例如,如果您正在构建一个需要立即同步的应用程序,例如远程控制应用程序,仍然可以通过调用setUrgent()立即完成同步,但对于更新联系人之类的操作,您可以容忍一些延迟非紧急数据项可能会延迟30分钟,但在大多数情况下,它们会在几分钟内送达低优先级现在是默认值,因此需要获取上一个计时
因此,如果您希望数据请求立即同步到其他连接的设备,请确保调用数据请求。哇,谢谢,这解决了手持设备上的问题!(我将其添加到手持设备和穿戴设备中)。现在它立即触发了数据更改。在我将数据发送到掌上电脑后,我的穿戴是无声的。我试图在手持设备上重写发送过程,就像它在磨损一样,但什么都没有。现在我已经更改了手持设备的磨损请求。从日志中(与问题类似),我看到请求已成功发送到正确的设备,但onDataChanged on wear未接收到请求(无论是否使用setUrgent())。若我通过MessageApi从手持设备发送消息,那个么它将被磨损的附加onMessageReceived接收。我想知道一个秘密,为什么MessageApi工作得很好,而DataAPI在某个地方丢失了。我发现数据可以通过以下修改之一达到磨损:在发送数据后,在手持设备上制作googleapi disconnect()和connect(),或者将Thread.start()替换为Thread.run()我甚至不知道,当有异步版本可以用来代替在线程上调用
await()
时,为什么要旋转整个新线程。