Search code examples
javaandroidwear-osandroid-wear-data-api

Not able to fetch data from Wear Data layer


I'm trying to sync a list from the handheld to the wearable. On the phone side, I have a listview and you can add items to it and on the wear side I am just displaying the same list. I'm adding items to /card/id path and adding the array size on /counter. OnDataChanged method does gets called when I add items to the list on phoneside, but when I try to read the items on wearside, it's not working. It gives nullpointer exception when I'm trying to get the connected nodes and therefor I'm not able to read the data. Here's the code and the log snapshot:

Error

04-15 12:41:38.075: E/AndroidRuntime(13791): Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'android.os.Looper com.google.android.gms.common.api.GoogleApiClient.getLooper()' on a null object reference

Wear side:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mDefaultCircleRadius = getResources().getDimension(R.dimen.default_settings_circle_radius);
    mSelectedCircleRadius = getResources().getDimension(R.dimen.selected_settings_circle_radius);
    cards = new ArrayList<GiftCard>();
    new LoadCards().execute();

    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.count_text);
            mListView = (WearableListView) stub.findViewById(R.id.card_list_view);

        }
    });

    mHandler = new Handler();
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Wearable.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

}


@Override
public void onDataChanged(DataEventBuffer dataEvents) {
    for (DataEvent event : dataEvents) {
        if (event.getType() == DataEvent.TYPE_CHANGED) {
            // DataItem changed
            DataItem item = event.getDataItem();
            if (item.getUri().getPath().compareTo(COUNT_PATH) == 0) {
                DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
                final String counter = dataMap.getString(CardUtil.CARD_COUNT);
                new LoadCards().execute();

                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(c,"Card count: "+ counter,Toast.LENGTH_LONG).show();

                        //mTextView.setText("COUNTER FROM DATACHANGE METHOD: " + counter);
                    }
                });


            }
            else if(item.getUri().getPath().compareTo(CARD_PATH) == 0){

            }
        } else if (event.getType() == DataEvent.TYPE_DELETED) {
            // DataItem deleted
        }
    }
}


public GiftCard loadCardData(int id){
    //Uri uri = getIntent().getData().buildUpon().encodedPath("/card").appendPath(String.valueOf(id)).build();
   Uri uri = getUriForDataItem("/counter");
    Log.d("URI", uri.getPath());
    DataApi.DataItemResult result = Wearable.DataApi.getDataItem(mGoogleApiClient,uri).await();

    DataMapItem item = DataMapItem.fromDataItem(result.getDataItem());
    Asset cardImageAsset = item.getDataMap().getAsset(CardUtil.CARD_IMAGE);
    //Asset barcodeImageAsset = item.getDataMap().getAsset(CardUtil.BARCODE_IMAGE);
    String card_type = item.getDataMap().getString(CardUtil.CARD_TYPE);
    Bitmap cardImage = BitmapFactory.decodeStream(Wearable.DataApi.getFdForAsset(mGoogleApiClient, cardImageAsset).await().getInputStream());
    //  Bitmap barcodeImage = BitmapFactory.decodeStream(Wearable.DataApi.getFdForAsset(mGoogleApiClient,barcodeImageAsset).await().getInputStream());
    GiftCard card = new GiftCard();
    card.setCardImage(cardImage);
    card.setCardName(card_type);
    card.setCardID(id);

    return card;
}

public class LoadCards extends AsyncTask<Void, Void, Boolean> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Boolean doInBackground(Void... arg0) {
       // Uri uri = getIntent().getData().buildUpon().encodedPath("/counter").build();
        Uri uri = getUriForDataItem("/counter");
        Toast.makeText(c,uri.toString(),Toast.LENGTH_LONG).show();
        DataApi.DataItemResult result = Wearable.DataApi.getDataItem(mGoogleApiClient,uri).await();

        DataMapItem item = DataMapItem.fromDataItem(result.getDataItem());
        int card_count = Integer.parseInt(item.getDataMap().getString(CardUtil.CARD_COUNT));
       // int card_count = Integer.parseInt(loadCardCounter());
        if(card_count <= 0){
            Toast.makeText(c,"No cards available to show!",Toast.LENGTH_LONG).show();
        } else {
            for (int i = 1; i <= card_count; i++) {
                GiftCard c = loadCardData(i);
                cards.add(c);
            }
        }
        return null;

    }

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);

        //update the card list
        mAdapter = new CardListAdapter(c,cards);
        mListView.setAdapter(mAdapter);
       // mListView.setClickListener();


    }
}

private Uri getUriForDataItem(String path) {

     String nodeId = getNodeId();

    return new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).authority(nodeId).path(path).build();
}


private String getNodeId() {

    NodeApi.GetConnectedNodesResult nodesResult = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
    List<Node> nodes = nodesResult.getNodes();
    if (nodes.size() > 0) {

        return nodes.get(0).getId();
    } else {
        Toast.makeText(c,"NO NODES AVAILABLE",Toast.LENGTH_LONG).show();
    }
    return null;
}}

Solution

  • From the stacktrace it's pretty obvious that you are trying to use Wearable DataAPI from the thread without Looper - in doInBackground() method I believe. That is why it crashes.

    Move this code directly into onDataChanged() method and it should solve the issue.