Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Wearable.DataApi.getFdForAsset produce a result with status 4005 (Asset Unavailable)?

I've written an Android Wear application which receives an image wrapped in an Asset from a phone app using the Data API. The app used to work fine and has not been changed in ages but recently I started to find the image passed from the phone app was failing to be rendered on the screen of the wearable. On investigation I found that one of the methods, getFdForAsset was failing with a wearable status code of 4005 which means Asset Unavailable. See https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableStatusCodes

I process data events in a call to my wearable app's onDataChanged method like this:

    public void onDataChanged(DataEventBuffer dataEvents) {
    LOGD(TAG, "XXXX MainActivity.onDataChanged()");

    final List<DataEvent> events = FreezableUtils.freezeIterable(dataEvents);
    dataEvents.close();

    LOGD(TAG, "onDataChanged data event count=" + events.size());
    for (DataEvent event : events) {
        if (event.getType() == DataEvent.TYPE_CHANGED) {
            String path = event.getDataItem().getUri().getPath();
            if (IMAGE_PATH.equals(path)) {
                DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem());
                LOGD(TAG, "onDataChanged getting image asset");
                Asset photo = dataMapItem.getDataMap()
                        .getAsset(IMAGE_KEY);
                LOGD(TAG, "onDataChanged photo asset="+photo);
                final String toi_name = dataMapItem.getDataMap().getString(GYBO_NAME);
                final String toi_info = dataMapItem.getDataMap().getString(GYBO_INFO);
                current_toi_name = toi_name;
                current_toi_info = toi_info;
                LOGD(TAG, "onDataChanged TOI name="+toi_name);
                LOGD(TAG, "onDataChanged TOI info="+toi_info);
                Bitmap bitmap = loadBitmapFromAsset(google_api_client, photo);

And then attempt to create a Bitmap from the Asset in this method:

    private Bitmap loadBitmapFromAsset(GoogleApiClient apiClient, Asset asset) {
    if (asset == null) {
        throw new IllegalArgumentException("XXXX Asset must be non-null");
    }

    DataApi.GetFdForAssetResult result = Wearable.DataApi.getFdForAsset(
            apiClient, asset).await();
    if (result == null) {
        Log.w(TAG, "XXXX getFdForAsset returned null");
        return null;
    }

    if (result.getStatus().isSuccess()) {
        Log.d(TAG, "XXXX loadBitmapFromAsset getFdForAsset was successful");
    } else {
        Log.d(TAG, "XXXX loadBitmapFromAsset getFdForAsset was not successful. Error="+result.getStatus().getStatusCode()+":"+result.getStatus().getStatusMessage());
        // Seeing status code 4005 here which means Asset Unavailable
    }

    InputStream assetInputStream = result.getInputStream();
    if (assetInputStream == null) {
        Log.w(TAG, "XXXX Requested an unknown Asset");
        result.release();
        return null;
    }
    result.release();
    return BitmapFactory.decodeStream(assetInputStream);
}

The Asset object itself is not null, so it's coming across from the mobile app OK. And the path of the data event is being correctly recognised as being one which contains an image.

Does anyone have any idea as to why I'm getting this result and how to resolve it?

Thanks

like image 566
martianw Avatar asked Oct 27 '25 05:10

martianw


2 Answers

one important thing... wearable as well as mobile module have to have the same signing certificate; just make sure if you define it via your build.gradle it's the same. this affects transferring assets... other data were synced w/o issues even with different certificates;

I was recently fighting with this issue and found this was the cause of ASSET_UNAVAILABLE, while adding wear module to existing app which had custom debug signing certificate defined in build.gradle - I had to have this certificate even for wearable for asset sync to work.

like image 90
ursimon Avatar answered Oct 28 '25 17:10

ursimon


How are you sending the image? I found that if I used Asset.createFromUri(), it didn't work and gave me the ASSET UNAVAILABLE error. But when I switched to Asset.createFromFd(), it worked.

Here's the code that worked for me:

    private static Asset createAssetFromBitmap(String imagePath) throws FileNotFoundException {
        // creating from Uri doesn't work: gives a ASSET_UNAVAILABLE error
        //return Asset.createFromUri(Uri.parse(imagePath));

        final File file = new File(imagePath);    
        final ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);

        return Asset.createFromFd(fd);
    }
like image 24
phreakhead Avatar answered Oct 28 '25 18:10

phreakhead