Android Wear sending data to Android phone, but phone appears to never receive it

*爱你&永不变心* 提交于 2020-01-21 04:51:09

问题


Short Summary: I am attempting to send data from an Android Wear watch to an Android phone using PutDataRequest and GoogleApiClient. Logs seem to show the data is sent successfully, but onDataChanged never fires. I am using Android Studio 1.0.2. I am not using any emulator but an Android Wear watch I own--which I have paired and enabled debugging via the Android Wear device and the Android Wear application on the phone. On both the phone and wear's AndroidManifest.xml, I include com.google.android.gms.version.

On the Android Phone (4.4.4 version of Android), I use a listener service, which is bound via the AndroidManifest.xml and started via the main activity on the phone. From logs, I can confirm the service is successfully created on the phone but no data is ever received (onDataChanged never fires -- to be precise).

    <!-- Phone manifest, registers the listener -->
    <service android:name=".DataLayerListenerService" >
        <intent-filter>
            <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
        </intent-filter>
    </service>

Here is the listener service, which runs on the phone:

public class DataLayerListenerService extends WearableListenerService {
    private static final String TAG = DataLayerListenerService.class.getName();
    private GoogleApiClient mGoogleApiClient;

    private static final String WEARABLE_DATA_PATH = "/audio";

    @Override
    public void onCreate() {
        // I can see this fires properly on the Android mobile phone
        Logger.d(TAG, "onCreate");
    }

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        // This never fires on the Android mobile phone, even though Wear says data was sent successfully
        Logger.d(TAG, "on change");
    }
}

On the Wear device, I have a main activity that creates a Google API client. I use a UI button to generate input from audio (code not shown), which I know is working right because of logging. I then attempt to send this data from the wear device to the phone. In the logs, I see "result available. Status: Status{statusCode=SUCCESS, resolution=null}" (I use a result callback to track).

public class MainActivity extends Activity implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener {
    private static final String TAG = MainActivity.class.getName();
    private static final int SPEECH_REQUEST_CODE = 1;

    private static final int RECORDER_SAMPLERATE = 44100;
    private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO;
    private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;

    private TextView mTextView;
    private AudioRecord recorder;
    private int bufferSize = 0;
    private Thread recordingThread = null;
    private GoogleApiClient mGoogleApiClient;
    private volatile boolean isRecording;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "Creating MainActivity");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        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);
            }
        });

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

    // Connect to the data layer when the Activity starts
    @Override
    protected void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

    protected void onResume() {
        if (null != mGoogleApiClient && !mGoogleApiClient.isConnected()) {
            mGoogleApiClient.connect();
        }
        super.onResume();
    }

    @Override
    protected void onStop() {
        if (null != mGoogleApiClient && mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
        }
        super.onStop();
    }

    // Placeholders for required connection callbacks
    @Override
    public void onConnectionSuspended(int cause) {
        Log.d(TAG, "Connection suspended");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d(TAG, "Connection failed");
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        Log.d(TAG, "Connected successfully");
    }

    // This is invoked from the UI, via a helper method not shown. Logs show the method is invoked fine.
    private void processRawAudioData() {
        byte data[] = new byte[bufferSize];
        int read = 0;
        while(isRecording) {
            read = recorder.read(data, 0, bufferSize);

            if(AudioRecord.ERROR_INVALID_OPERATION != read) {
                Log.d(TAG, "Successfully read " + data.length + " bytes of audio");
                Log.d(TAG, "Initial ten bytes: " + data[0] + data[1] + data[2] + data[3]
                    + data[4] + data[5] + data[6] + data[7] + data[8] + data[9] + data[10]);

                Asset myAsset = Asset.createFromBytes(data);
                PutDataRequest request = PutDataRequest.create("/audio");
                // might need to change time each time for other end to see change.
                request.putAsset("profileImage", myAsset);
                PendingResult<DataApi.DataItemResult> result =
                    Wearable.DataApi.putDataItem(mGoogleApiClient, request);
                result.setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
                    @Override
                    public void onResult(DataApi.DataItemResult dataItemResult) {
                     // LOGS SHOW STATUS "MainActivity﹕ result available. Status: Status{statusCode=SUCCESS, resolution=null}"   
                     Log.d(TAG, "result available. Status: " + dataItemResult.getStatus());
                    }
                });
            }
        }
    }
}

回答1:


In order for the WearableListenerService to fire the 'onDataChanged' event, the applicationId's in the main app and wearable app must match (build.gradle files).

In addition, you cannot send static data, the data must change. That means data in your PutDataMapRequest object must be changing.




回答2:


I had the same issue and from what I read on Google developers, onDataChanged will never be triggered on the device because it does not listen to events from the wearable device :

For example, you can have a handheld app that sets and gets data item objects and a wearable app that listens for these updates to update it's UI. The wearable never updates any of the data items, so the handheld app doesn't listen for any data events from the wearable app.

https://developer.android.com/training/wearables/data-layer/events.html#Listen




回答3:


add a key value in the send dataapimap map.put("timestamp", System.currentmillions())




回答4:


Did your onReceive gets called ??

I had a similar problem where Handheld device sends a data but Listener service do not get called. This was due to inconsistency between app and wear gradle files.

My app had multiple flavors which I had to remove and make grade same as wear and all worked smoothly there after




回答5:


have u added the Wearable.DataApi.addListener() in the listener side app?




回答6:


Ok, so I had this same problem, and I found out I was not connected at the time the event was sent from the mobile, so I never saw it. The key is: onDataChanged() will not fire unless the GoogleApiClient is connected and listening at the time of sending. It does not seem to send you the events you missed as soon as you reconnect; you have to manually poll for the missed DataItems when you connect().

At least, that's seems like a bug to me: I would expect onDataChanged() to fire with any events that were sent in the time the client was disconnected. Am I wrong in assuming that?

Anyway, here's how I manually polled for the events I missed each time I connect:

@Override
public void onConnected(Bundle bundle) {

    Wearable.DataApi.addListener(googleApiClient, this);

    syncPresets();
}
@Override
public void onConnectionSuspended(int i) {

    Wearable.DataApi.removeListener(googleApiClient, this);
}

private void syncPresets() {

    // Ok, so the reason is, we're calling Wearable.DataApi.addListener(googleApiClient, this);
    // only when we connect. 
    // thus, we manually poll for the ones we missed...
    Wearable.DataApi.getDataItems(googleApiClient, getDataUri(WEARABLE_DATA_PATH))
            .setResultCallback(new ResultCallback<DataItemBuffer>() {
                @Override
                public void onResult(DataItemBuffer dataItems) {
                    Status status = dataItems.getStatus();

                    if (status.isSuccess()) {

                        for (DataItem dataItem : dataItems) {

                            Log.d(TAG, "Synced image " + dataItem);
                            if (dataItem != null) {



                                // do whatever you do with the items here...
                                onReceivedImage(dataItem);



                            }
                        }
                    } else {
                        Log.d(TAG, "Failed getting image: (" + status.getStatusCode() + ") " + status.getStatusMessage());
                    }

                    dataItems.release();
                }
            });
}


来源:https://stackoverflow.com/questions/28034315/android-wear-sending-data-to-android-phone-but-phone-appears-to-never-receive-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!