I want to make bidirectional data transfer between Android Wear and Handheld.
All seems to be good except triggering onDataChanged on Handheld. It triggers only then I plug inout USB cable, connected to the PC.
So I don't understand why it's happen.
Here is my code:
WearListenerService on Handheld:
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");
}
}
}
}
}
WearListenerService on Wear:
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.DataItem
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…