Steps
Note - Above steps are for Android studio wizard. Sorry for eclipse developers (Please migrate to AS)
Step - 2
So our android wear module is added. I hope you have no issue in above steps. in the main activity or launcher activity i have created a List (basically list of my tutorials). For learning purpose you can start with same and after that you can change it is as you want. so put below code in appropriate layout files.
wear/layout/activity_list.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.wearable.view.WatchViewStub xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/watch_view_stub" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#e4e5e5" app:rectLayout="@layout/rect_activity_list" app:roundLayout="@layout/round_activity_list" tools:context=".ListActivity" tools:deviceIds="wear"> </android.support.wearable.view.WatchViewStub>
wear/layout/rect_activity_list.xml & wear/layout/round_activity_list.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.wearable.view.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context=".ListActivity" tools:deviceIds="wear_round"> <android.support.wearable.view.WearableListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="5dp" android:overScrollMode="never" /> <TextView android:id="@+id/tv_header" android:layout_width="wrap_content" android:layout_height="40dp" android:layout_gravity="top|center" android:textSize="30sp" android:layout_marginTop="10dp" android:textColor="#52bf90" android:fontFamily="sans-serif-light" android:text="@string/app_name"/> </android.support.wearable.view.BoxInsetLayout>
Step - 3
List layout is done in Step -2. now let's jump to coding part where i have initialize WearableListView with Array adapter. Using GoogleApiClient i have checked if there is a connection to a android wear from an app or not. we can get all connected nodes or devices using Wearable.NodeApi.getConnectedNodes method. check below code and make sure you understand or go through it for one time so you know what is actually going on. otherwise you will get confused.
wear/java/ListActivity.java
package com.androprogrammer.tutorials; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.wearable.view.WatchViewStub; import android.support.wearable.view.WearableListView; import android.util.Log; import android.view.LayoutInflater; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.wearable.MessageApi; import com.google.android.gms.wearable.Node; import com.google.android.gms.wearable.NodeApi; import com.google.android.gms.wearable.Wearable; import java.util.ArrayList; public class ListActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,WearableListView.ClickListener { private WearableListView mListView; private ArrayList<String> listItems; Node mNode; // the connected device to send the message to GoogleApiClient mGoogleApiClient; private boolean mResolvingError=false; public static String SERVICE_CALLED_WEAR = "WearListClicked"; public static String TAG = "WearListActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list); //Connect the GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this) .addApi(Wearable.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build(); initializeListItems(); final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub); stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() { @Override public void onLayoutInflated(WatchViewStub stub) { mListView = (WearableListView) stub.findViewById(R.id.listView1); mListView.setAdapter(new MyAdapter(ListActivity.this, listItems)); mListView.setClickListener(ListActivity.this); } }); } private void initializeListItems() { listItems = new ArrayList<>(); listItems.add("Async File Read"); listItems.add("Battery Status"); listItems.add("Volume Setting"); listItems.add("Frame Animation"); listItems.add("Video Player"); listItems.add("Circular Image View"); listItems.add("Track User Location"); listItems.add("Take Image"); listItems.add("Image Grid View"); listItems.add("Image Switcher"); listItems.add("Tabs with Toolbar"); listItems.add("Icon Tabs with Toolbar"); listItems.add("Push Notification"); } @Override protected void onStart() { super.onStart(); if (!mResolvingError) { mGoogleApiClient.connect(); } } /** * Resolve the node = the connected device to send the message to */ private void resolveNode() { Wearable.NodeApi.getConnectedNodes(mGoogleApiClient) .setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() { @Override public void onResult(NodeApi.GetConnectedNodesResult nodes) { for (Node node : nodes.getNodes()) { mNode = node; } } }); } @Override public void onConnected(Bundle bundle) { resolveNode(); } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(ConnectionResult connectionResult) { } /** * Send message to mobile handheld */ private void sendMessage(String Key) { if (mNode != null && mGoogleApiClient!= null && mGoogleApiClient.isConnected()) { Log.d(TAG, "-- " + mGoogleApiClient.isConnected()); Wearable.MessageApi.sendMessage( mGoogleApiClient, mNode.getId(), SERVICE_CALLED_WEAR + "--" + Key, null).setResultCallback( new ResultCallback<MessageApi.SendMessageResult>() { @Override public void onResult(MessageApi.SendMessageResult sendMessageResult) { if (!sendMessageResult.getStatus().isSuccess()) { Log.e(TAG, "Failed to send message with status code: " + sendMessageResult.getStatus().getStatusCode()); } } } ); } } @Override public void onClick(WearableListView.ViewHolder viewHolder) { TextView view = (TextView) viewHolder.itemView.findViewById(R.id.row_tv_name); String Key = view.getText().toString(); Log.d(TAG, Key); sendMessage(Key); } @Override public void onTopEmptyRegionClick() { Toast.makeText(this, "You tapped on Top empty area", Toast.LENGTH_SHORT).show(); } private class MyAdapter extends WearableListView.Adapter { private final LayoutInflater mInflater; private ArrayList<String> data; private MyAdapter(Context context, ArrayList<String> listItems) { mInflater = LayoutInflater.from(context); data = listItems; } @Override public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new WearableListView.ViewHolder( mInflater.inflate(R.layout.row_wear_list, null)); } @Override public void onBindViewHolder(WearableListView.ViewHolder holder, int position) { TextView view = (TextView) holder.itemView.findViewById(R.id.row_tv_name); view.setText(data.get(position)); holder.itemView.setTag(position); } @Override public int getItemCount() { return data.size(); } } }
wear/layout/row_wear_list.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="80dp" android:orientation="horizontal" android:padding="8dp" android:gravity="center"> <TextView android:textAppearance="?android:attr/textAppearanceMedium" android:text="Medium Text" android:textStyle="bold" android:ellipsize="end" android:maxEms="15" android:padding="10dp" android:ems="15" android:background="@android:color/white" android:textColor="@android:color/black" android:fontFamily="sans-serif-condensed-light" android:gravity="center" android:layout_height="match_parent" android:layout_width="wrap_content" android:textSize="16sp" android:id="@+id/row_tv_name" /> </LinearLayout>
wear/AndroidManifest.xml
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
Please add above lines of code in manifest file of wear module. because we are using google play service to communicate. otherwise it will give error.
Step - 4
Now android wear module is ready. you can run it separately on emulator and check it. now we require a bridge which can pass android wear message to android mobile app. so when user click on list item in android wear a service get some sort of message and on the basis of that message we start appropriate activity. Using WearableListenerService we will create service which will do same for our app.
mobile/java/WearListCallListenerService.java
package com.androprogrammer.tutorials.services; import android.content.Intent; import android.util.Log; import com.androprogrammer.tutorials.activities.Listactivity; import com.google.android.gms.wearable.MessageEvent; import com.google.android.gms.wearable.WearableListenerService; /** * Created by Wasim on 08-05-2015. */ public class WearListCallListenerService extends WearableListenerService { public static String SERVICE_CALLED_WEAR = "WearListClicked"; @Override public void onMessageReceived(MessageEvent messageEvent) { super.onMessageReceived(messageEvent); String event = messageEvent.getPath(); Log.d("Listclicked", event); String [] message = event.split("--"); if (message[0].equals(SERVICE_CALLED_WEAR)) { startActivity(new Intent((Intent) Listactivity.getInstance().tutorials.get(message[1])) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } } }
Step - 5
In Mobile app put below code to register your service.
mobile/AndroidManifest.xml
<service android:name=".services.WearListCallListenerService"> <intent-filter> <action android:name="com.google.android.gms.wearable.BIND_LISTENER" /> </intent-filter> </service>
That's it...
Now run wear module in android wear emulator and mobile module in device. make sure you are connected. I hope you understand the full tutorial. you can get full source code from my Github repo. if you find it helpful please share this tutorial.
Keep coding...