每当您打开穿戴应用程序时,同步 Android 穿戴与 Phone
Sync Android Wear with Phone whenever you open the wear app
我正在尝试为 android phone 和 wear 实现一个基本的天气应用程序。该应用程序从 Web API 获取数据,然后将其显示在 phone 上。现在,如果该应用程序在 Wear 上打开,然后您在 Phone 上打开它,它会同步两者的天气。如果你改变 phone 上的天气,它也会改变穿着。每当您打开磨损应用程序时,我想让磨损应用程序从 phone 获取天气,我试图通过消息使磨损 "ping" 成为 phone 来实现这一点,然后phone 通过数据映射发送信息。这有效,除了 wear 没有从 phone 接收数据映射,尽管 phone 说它已经发送了数据映射。
穿主Activity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_data_map);
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override
public void onLayoutInflated(WatchViewStub stub) {
mTextView = (TextView) stub.findViewById(R.id.text);
sendMessage("Ping");
Log.i("OnLayoutInflated","LAYOUT INFLATED");
}
});
setAmbientEnabled();
// Register the local broadcast receiver
IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
MessageReceiver messageReceiver = new MessageReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, messageFilter);
}
@Override
protected void onPause() {
super.onPause();
if (wearCommsManager.isConnected()) {
wearCommsManager.disconnectClient();
}
}
@Override
protected void onResume() {
super.onResume();
if (wearCommsManager == null) {
wearCommsManager = new WearCommsManager(this);
}
if (messageSender == null) {
messageSender = new WearMessageSender(wearCommsManager);
}
verifyCommsConnection();
}
protected void sendMessage(final String message) {
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {;
messageSender.processRequest(message);
return null;
}
};
task.execute();
}
private void verifyCommsConnection() {
new WearCommsManager(this).verifyCommsConnection(new WearCommsManager.CommsCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailure() {
Log.e("ERROR","CONNECTION FAILED");
}
});
}
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle data = intent.getBundleExtra("datamap");
// Display received data in UI
String display =
data.getString("city") + "\n" +
data.getString("temperature") + "\n" +
data.getString("wind_speed") + "\n" +
data.getString("cloud_percent")+"\n"+
data.getString("lastupdate");
mTextView.setText(display);
}
}
佩戴监听器:
public class ListenerService extends WearableListenerService{
private static final String WEARABLE_DATA_PATH = "/wearable_data";
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
DataMap dataMap;
for (DataEvent event : dataEvents) {
Log.v("myTag", "DataMap received on watch: " + DataMapItem.fromDataItem(event.getDataItem()).getDataMap());
// Check the data type
if (event.getType() == DataEvent.TYPE_CHANGED) {
// Check the data path
String path = event.getDataItem().getUri().getPath();
if (path.equals(WEARABLE_DATA_PATH)) {}
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
// Broadcast DataMap contents to wearable activity for display
// The content has the golf hole number and distances to the front,
// middle and back pin placements.
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("datamap", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
}
}
}
}
Phone 主要 Activity:
public class DataMapActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
private TextView cityName;
private TextView temp;
private ImageView iconView;
private TextView description;
private TextView humidity;
private TextView pressure;
private TextView wind;
private TextView sunrise;
private TextView sunset;
private TextView updated;
Weather weather = new Weather();
GoogleApiClient googleClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_data_map);
cityName = (TextView) findViewById(R.id.cityText);
iconView = (ImageView) findViewById(R.id.thumbnailIcon);
temp = (TextView) findViewById(R.id.tempText);
description = (TextView) findViewById(R.id.CloudText);
humidity = (TextView) findViewById(R.id.HumidText);
pressure = (TextView) findViewById(R.id.PressureText);
wind = (TextView) findViewById(R.id.WindText);
sunrise = (TextView) findViewById(R.id.RiseText);
sunset = (TextView) findViewById(R.id.SetText);
updated = (TextView) findViewById(R.id.UpdateText);
CityPreference cityPreference=new CityPreference(DataMapActivity.this);
System.out.println(cityPreference.getCity());
renderWeatherData(cityPreference.getCity());
IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
MessageReceiver messageReceiver = new MessageReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, messageFilter);
// Build a new GoogleApiClient for the the Wearable API
googleClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
public void renderWeatherData(String city) {
WeatherTask weatherTask = new WeatherTask();
weatherTask.execute(new String[]{city + "&units=metric"});
}
private class WeatherTask extends AsyncTask<String, Void, Weather> {
@Override
protected Weather doInBackground(String... params) {
String data = ((new WeatherHttpClient()).getWeatherData(params[0]));
System.out.println(data);
weather = JSONParser.getWeather(data);
return weather;
}
@Override
protected void onPostExecute(Weather weather) {
super.onPostExecute(weather);
if(weather.currentCondition.getIcon() != null){
new DownloadImageAsyncTask().execute(weather.currentCondition.getIcon());
}
cityName.setText(weather.place.getCity() + "," + weather.place.getCountry());
temp.setText("" + (int)weather.currentCondition.getTemperature() + "°C");
wind.setText("Wind Speed: " + weather.wind.getSpeed()+"m/s" + " Degree: " + weather.wind.getDegree());
description.setText("Clouds: " + weather.clouds.getPrecipitation() + "%, " + weather.currentCondition.getDescription());
pressure.setText("Pressure: " + weather.currentCondition.getPressure()+"hpa");
humidity.setText("Humidity: " + weather.currentCondition.getHumidity()+"%");
Date mydate = new Date(weather.place.getSunrise() * 1000);
SimpleDateFormat dateformat = new SimpleDateFormat("HH:mm");
dateformat.setTimeZone(TimeZone.getTimeZone("GMT+3"));
String date = dateformat.format(mydate);
sunrise.setText("Sunrise: " + date);
mydate = new Date(weather.place.getSunset() * 1000);
date = dateformat.format(mydate);
sunset.setText("Sunset: " + date);
mydate = new Date(weather.place.getLastupdate() * 1000);
dateformat = new SimpleDateFormat("dd.MM.yyyy, HH:mm, z");
dateformat.setTimeZone(TimeZone.getDefault());
date = dateformat.format(mydate);
updated.setText("Last Updated: " + date);
sendWear();
//This part synchronizes perfectly with wear
}
}
private void sendWear(){
String WEARABLE_DATA_PATH = "/wear_data";
// Create a DataMap object and send it to the data layer
DataMap dataMap = new DataMap();
dataMap.putString("lastupdate", updated.getText().toString());
dataMap.putString("city", cityName.getText().toString());
dataMap.putString("temperature", temp.getText().toString());
dataMap.putString("wind_speed", wind.getText().toString());
dataMap.putString("cloud_percent", description.getText().toString());
//Requires a new thread to avoid blocking the UI
new SendToDataLayerThread(WEARABLE_DATA_PATH, dataMap).start();
}
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String s= intent.getStringExtra("Pinger");
if(s!=null) {
new SendToWearAsyncTask().execute();
}
}
}
private class SendToWearAsyncTask extends AsyncTask<Void,Void,Void>{
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
sendWear();
//this part wear doesn't receive the datamap
}
@Override
protected Void doInBackground(Void... params) {
return null;
}
}
确保 applicationID
were the same in the build.gradle for mobile and wear app. Also make sure that the buildTypes
part and the signingConfigs
part are the same in both apps. You can also send 每次更改时都进行验证。
我正在尝试为 android phone 和 wear 实现一个基本的天气应用程序。该应用程序从 Web API 获取数据,然后将其显示在 phone 上。现在,如果该应用程序在 Wear 上打开,然后您在 Phone 上打开它,它会同步两者的天气。如果你改变 phone 上的天气,它也会改变穿着。每当您打开磨损应用程序时,我想让磨损应用程序从 phone 获取天气,我试图通过消息使磨损 "ping" 成为 phone 来实现这一点,然后phone 通过数据映射发送信息。这有效,除了 wear 没有从 phone 接收数据映射,尽管 phone 说它已经发送了数据映射。
穿主Activity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_data_map);
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override
public void onLayoutInflated(WatchViewStub stub) {
mTextView = (TextView) stub.findViewById(R.id.text);
sendMessage("Ping");
Log.i("OnLayoutInflated","LAYOUT INFLATED");
}
});
setAmbientEnabled();
// Register the local broadcast receiver
IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
MessageReceiver messageReceiver = new MessageReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, messageFilter);
}
@Override
protected void onPause() {
super.onPause();
if (wearCommsManager.isConnected()) {
wearCommsManager.disconnectClient();
}
}
@Override
protected void onResume() {
super.onResume();
if (wearCommsManager == null) {
wearCommsManager = new WearCommsManager(this);
}
if (messageSender == null) {
messageSender = new WearMessageSender(wearCommsManager);
}
verifyCommsConnection();
}
protected void sendMessage(final String message) {
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {;
messageSender.processRequest(message);
return null;
}
};
task.execute();
}
private void verifyCommsConnection() {
new WearCommsManager(this).verifyCommsConnection(new WearCommsManager.CommsCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailure() {
Log.e("ERROR","CONNECTION FAILED");
}
});
}
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle data = intent.getBundleExtra("datamap");
// Display received data in UI
String display =
data.getString("city") + "\n" +
data.getString("temperature") + "\n" +
data.getString("wind_speed") + "\n" +
data.getString("cloud_percent")+"\n"+
data.getString("lastupdate");
mTextView.setText(display);
}
}
佩戴监听器:
public class ListenerService extends WearableListenerService{
private static final String WEARABLE_DATA_PATH = "/wearable_data";
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
DataMap dataMap;
for (DataEvent event : dataEvents) {
Log.v("myTag", "DataMap received on watch: " + DataMapItem.fromDataItem(event.getDataItem()).getDataMap());
// Check the data type
if (event.getType() == DataEvent.TYPE_CHANGED) {
// Check the data path
String path = event.getDataItem().getUri().getPath();
if (path.equals(WEARABLE_DATA_PATH)) {}
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
// Broadcast DataMap contents to wearable activity for display
// The content has the golf hole number and distances to the front,
// middle and back pin placements.
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("datamap", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
}
}
}
}
Phone 主要 Activity:
public class DataMapActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
private TextView cityName;
private TextView temp;
private ImageView iconView;
private TextView description;
private TextView humidity;
private TextView pressure;
private TextView wind;
private TextView sunrise;
private TextView sunset;
private TextView updated;
Weather weather = new Weather();
GoogleApiClient googleClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_data_map);
cityName = (TextView) findViewById(R.id.cityText);
iconView = (ImageView) findViewById(R.id.thumbnailIcon);
temp = (TextView) findViewById(R.id.tempText);
description = (TextView) findViewById(R.id.CloudText);
humidity = (TextView) findViewById(R.id.HumidText);
pressure = (TextView) findViewById(R.id.PressureText);
wind = (TextView) findViewById(R.id.WindText);
sunrise = (TextView) findViewById(R.id.RiseText);
sunset = (TextView) findViewById(R.id.SetText);
updated = (TextView) findViewById(R.id.UpdateText);
CityPreference cityPreference=new CityPreference(DataMapActivity.this);
System.out.println(cityPreference.getCity());
renderWeatherData(cityPreference.getCity());
IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
MessageReceiver messageReceiver = new MessageReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, messageFilter);
// Build a new GoogleApiClient for the the Wearable API
googleClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
public void renderWeatherData(String city) {
WeatherTask weatherTask = new WeatherTask();
weatherTask.execute(new String[]{city + "&units=metric"});
}
private class WeatherTask extends AsyncTask<String, Void, Weather> {
@Override
protected Weather doInBackground(String... params) {
String data = ((new WeatherHttpClient()).getWeatherData(params[0]));
System.out.println(data);
weather = JSONParser.getWeather(data);
return weather;
}
@Override
protected void onPostExecute(Weather weather) {
super.onPostExecute(weather);
if(weather.currentCondition.getIcon() != null){
new DownloadImageAsyncTask().execute(weather.currentCondition.getIcon());
}
cityName.setText(weather.place.getCity() + "," + weather.place.getCountry());
temp.setText("" + (int)weather.currentCondition.getTemperature() + "°C");
wind.setText("Wind Speed: " + weather.wind.getSpeed()+"m/s" + " Degree: " + weather.wind.getDegree());
description.setText("Clouds: " + weather.clouds.getPrecipitation() + "%, " + weather.currentCondition.getDescription());
pressure.setText("Pressure: " + weather.currentCondition.getPressure()+"hpa");
humidity.setText("Humidity: " + weather.currentCondition.getHumidity()+"%");
Date mydate = new Date(weather.place.getSunrise() * 1000);
SimpleDateFormat dateformat = new SimpleDateFormat("HH:mm");
dateformat.setTimeZone(TimeZone.getTimeZone("GMT+3"));
String date = dateformat.format(mydate);
sunrise.setText("Sunrise: " + date);
mydate = new Date(weather.place.getSunset() * 1000);
date = dateformat.format(mydate);
sunset.setText("Sunset: " + date);
mydate = new Date(weather.place.getLastupdate() * 1000);
dateformat = new SimpleDateFormat("dd.MM.yyyy, HH:mm, z");
dateformat.setTimeZone(TimeZone.getDefault());
date = dateformat.format(mydate);
updated.setText("Last Updated: " + date);
sendWear();
//This part synchronizes perfectly with wear
}
}
private void sendWear(){
String WEARABLE_DATA_PATH = "/wear_data";
// Create a DataMap object and send it to the data layer
DataMap dataMap = new DataMap();
dataMap.putString("lastupdate", updated.getText().toString());
dataMap.putString("city", cityName.getText().toString());
dataMap.putString("temperature", temp.getText().toString());
dataMap.putString("wind_speed", wind.getText().toString());
dataMap.putString("cloud_percent", description.getText().toString());
//Requires a new thread to avoid blocking the UI
new SendToDataLayerThread(WEARABLE_DATA_PATH, dataMap).start();
}
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String s= intent.getStringExtra("Pinger");
if(s!=null) {
new SendToWearAsyncTask().execute();
}
}
}
private class SendToWearAsyncTask extends AsyncTask<Void,Void,Void>{
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
sendWear();
//this part wear doesn't receive the datamap
}
@Override
protected Void doInBackground(Void... params) {
return null;
}
}
确保 applicationID
were the same in the build.gradle for mobile and wear app. Also make sure that the buildTypes
part and the signingConfigs
part are the same in both apps.