不得在UI线程上调用Android-await

时间:2018-06-20 03:13:11

标签: java android wear-os

我正在尝试编写一个Wear OS应用,该应用将IMU传感器数据记录为二进制文件并将其发送到手机。

@Override
public void onDataChanged(DataEventBuffer dataEvents) {
    final List<DataEvent> events = FreezableUtils.freezeIterable(dataEvents);
     dataEvents.close();
     Log.e("List Size: ", String.valueOf(events.size()));
     for (DataEvent event : events){
         if (event.getType() == DataEvent.TYPE_CHANGED){
             Log.v("Data is changed", "========================");
             String path = event.getDataItem().getUri().getPath();
             if(SENSOR_DATA_PATH.equals(path)){
                 DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem());
                 Asset fileAsset = dataMapItem.getDataMap().getAsset("File");
                 WriteToFilesFromAsset(mGoogleApiClient, fileAsset);
             }
         }
     }
     status.setText("Received!!");
}

private void WriteToFilesFromAsset(GoogleApiClient googleApiClient, Asset asset){
    String FileName = "_Activity.bin";

    File dataFile = new File(Environment.getExternalStorageDirectory().toString()+"/DataFiles", FileName);

    if (asset == null){
        throw new IllegalArgumentException("Asset must be non-null");
    }
    //The line below breaks the app
    InputStream assetInputStream = Wearable.DataApi.getFdForAsset(googleApiClient, asset).await().getInputStream();
   byte[] buffer = new byte[BUFFER_SIZE];
    int byteRead;
    try{
        FileOutputStream fos = new FileOutputStream(dataFile);
        while(  (byteRead = assetInputStream.read()) != -1){
            fos.write(byteRead);
        }
        assetInputStream.close();
        fos.close();
    }
    catch(IOException ex){
        Log.e("IO", ex.toString());
    }
    Log.i("Type", assetInputStream.toString());
    return ;
}

我收到一条错误消息,说不能在UI线程上调用await。

我在SO上发现了类似的问题,但没有一个能够解决我的问题。

如果您能帮助我修复此错误,我将不胜感激。

谢谢!

2 个答案:

答案 0 :(得分:2)

您正在使用的API受到限制,不允许您从UI(AKA主)线程中调用await。 Android中有几种API可以帮助您保护开发人员避免做愚蠢的事情。如果您阻止UI线程,则操作系统将无法绘制您的应用程序,因此它似乎挂在用户面前,最终将导致ANR错误。

在这种情况下,您尝试执行的任务可能需要一段时间,因此您需要退出UI线程并在后台线程中完成操作。有几种方法可以做到这一点。从setResultCallback返回的PendingResult上有一个getFdForAsset方法,可以解决等待问题。但是,您稍后将执行一些I / O来保存数据,这也将给您带来类似的错误,因为您也不应该在IU线程上执行此操作。您需要将整个操作放在后台线程上。

以下是一些用于执行后台任务的文档。 https://developer.android.com/training/best-background

答案 1 :(得分:0)

尝试

    private void WriteToFilesFromAsset(GoogleApiClient googleApiClient, Asset asset) {
    String FileName = "_Activity.bin";

    File dataFile = new File(Environment.getExternalStorageDirectory().toString() + "/DataFiles", FileName);

    if (asset == null) {
        throw new IllegalArgumentException("Asset must be non-null");
    }

    new Thread(new Runnable() {
        @Override
        public void run() {
            //The line below breaks the app
            InputStream assetInputStream = Wearable.DataApi.getFdForAsset(googleApiClient, asset).await().getInputStream();
            byte[] buffer = new byte[BUFFER_SIZE];
            int byteRead;
            try {
                FileOutputStream fos = new FileOutputStream(dataFile);
                while ((byteRead = assetInputStream.read()) != -1) {
                    fos.write(byteRead);
                }
                assetInputStream.close();
                fos.close();
            } catch (IOException ex) {
                Log.e("IO", ex.toString());
            }
            Log.i("Type", assetInputStream.toString());
        }
    }).start();
}