-1

App Runtime for Chrome でコンパイルされた、Chrome OS 用に調整された Android アプリの外部ファイルへの書き込みに関して問題があります。このアプリ機能は、2 つの Android テスト デバイス (1 つの API 19、ARC と同じ) で意図したとおりに動作しますが、Chromebook でテストすると常に失敗します。私のminSdkVersionアプリのはです19

私のアプリはテキスト エディターです。達成したいのは、 を使用してテキストを読み込み、その過程でIntent.ACTION_OPEN_DOCUMENTファイルを保存することです。Uri後で保存したいときに、これUriを使用してファイルにアクセスし、その内容を更新できます。ユーザーがファイルを保存するたびに「共有」ダイアログで邪魔する必要はありません (または自動保存を設定している場合)。がある場合、私のアプリはデフォルトでACTION_SENDインテントに設定されFileNotFoundExceptionます)。

関連するコードは次のとおりです。誰かが回避策、または私ができる改善を提案できますか?

public class EditorHost extends AppCompatActivity implements EditorFragment.EditorInterface {

private static final int REQUEST_OPEN = 15;

//...

 @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (mEditorFragmentChild == null)
            mEditorFragmentChild = (EditorFragment) mFragmentManager.findFragmentByTag(EDITOR_FRAGMENT_TAG);
        switch (item.getItemId()) {
            case R.id.load_file:
                open();
                break;
            case R.id.save_file:
                if (mEditorFragmentChild.getUri() == null){
                    shareTask();
                    break;
                }
                mEditorFragmentChild.saveTask();
                break;
            case R.id.share:
                mIntent = new Intent(Intent.ACTION_SEND);
                mIntent.putExtra(Intent.EXTRA_TEXT, mEditorFragmentChild.mExtendedEditText.getText().toString());
                mIntent.setType("text/plain");
                startActivity(Intent.createChooser(mIntent, getString(R.string.share_title)));
                break;

@TargetApi(Build.VERSION_CODES.KITKAT)
private void open(){
    mIntent = new Intent().setType("text/plain");
    startActivityForResult(mIntent.setAction(Intent.ACTION_OPEN_DOCUMENT).addCategory(Intent.CATEGORY_OPENABLE), REQUEST_OPEN);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData){
    if (resultCode == Activity.RESULT_OK){
        Uri uri = null;

        if (resultData != null) {
            uri = resultData.getData();

            if (requestCode == REQUEST_OPEN) {
                Cursor c = getContentResolver().query(uri,null, null, null, null);

                if (c != null && c.moveToFirst()){
                    title = c.getString(c.getColumnIndex(OpenableColumns.DISPLAY_NAME));

                    String[] cols = c.getColumnNames();
                    for (int i = 0; i < c.getColumnCount(); i++){
                        Log.e(LOG_TAG, cols[i]);
                    }

                    content = readFromFile(uri);

                    if (title == null || title.equals("")){
                        title = getString(R.string.app_name);
                    }

                    getSupportActionBar().setTitle(title);
                    mEditorFragmentChild.updateTextFromFile(content.trim());
                    mEditorFragmentChild.setUri(uri.toString());

                    if (!c.isClosed()) {
                        c.close();
                    }
                }
            }
        }
    }
}

そしてEditorFragmentクラスで:

public class EditorFragment extends Fragment implements ... {
//...
String getUri(){
    return mUri;
}

void setUri(String newUri){
    mUri = newUri;
}

void saveTask(){
    if (mUri == null || fromShareTask) {
        fromShareTask = false;
        return;
    }
    try {
        OutputStream outputStream = mAppCompatActivity.getContentResolver().openOutputStream(Uri.parse(mUri));
        outputStream.write(mExtendedEditText.getText().toString().getBytes());
        outputStream.close();
        //Toast.makeText(mAppCompatActivity, mAppCompatActivity.getString(R.string.file_updated_confirmation), Toast.LENGTH_SHORT).show();
    } catch (IOException e){
        e.printStackTrace();
        dispatchShareEvent();
        Toast.makeText(mAppCompatActivity, mAppCompatActivity.getString(R.string.save_failed), Toast.LENGTH_LONG).show();
        mExtendedEditText.setText(e.toString() + "\n\n" + exceptionStacktraceToString(e) + "\n\n" + "mUri is " + mUri);
    }
}

最後に、エラー メッセージ (上から繰り返しますが、これは私の Chromebook でのみ発生し、Android テスト デバイスでは発生しません):

java.io.FileNotFoundException: Can't access data/data/org.chromium.arc/external/(etc.)...

ありがとう!

編集:

Chromebook からスタック トレースを取得する方法がわかりませんでしたが、この質問に対する受け入れられた回答から次のメソッドを追加して、EditText. も最後に印刷しUriました。出力は次のとおりです。

java.io.FileNotFoundException: Can't access /data/data/org.chromium.arc/external/E5783234425D1719508FC512B2BEE2A5/1kTest.txt
java.io.FileNotFoundException: Can't access /data/data/org.chromium.arc/external/E5783234425D1719508FC512B2BEE2A5/1kTest.txt
at com.android.providers.media.MediaProvider.checkAccess(MediaProvider.java:4620)
at com.android.providers.media.MediaProvider.openFileAndEnforcePathPermissionsHelper(MediaProvider.java:4569)
at com.android.providers.media.MediaProvider.openFile(MediaProvider.java:4493)
at android.content.ContentProvider.openAssetFile(ContentProvider.java:1211)
at android.content.ContentProvider.openAssetFile(ContentProvider.java:1274)
at android.content.ContentProvider$Transport.openAssetFile(ContentProvider.java:314)
at android.content.ContentProvider$Transport.openAssetFile(Native Method)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:926)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:673)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:649)
at com.werdpressed.partisan.filterforchrome.EditorFragment.saveTask(EditorFragment.java:370)
at com.werdpressed.partisan.filterforchrome.EditorHost.onOptionsItemSelected(EditorHost.java:119)
at android.app.Activity.onMenuItemSelected(Activity.java:2619)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:353)
at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:144)
at android.support.v7.internal.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:99)
at android.support.v7.app.AppCompatDelegateImplV7.onMenuItemSelected(AppCompatDelegateImplV7.java:538)
at android.support.v7.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:802)
at android.support.v7.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:153)
at android.support.v7.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:949)
at android.support.v7.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:939)
at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:598)
at android.support.v7.internal.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:139)
at android.view.View.performClick(View.java:4440)
at android.view.View$PerformClick.run(View.java:18407)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:5181)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at android.os.Process$1.run(Process.java:418)

mUri is content://media/external/file/8

エラーは次のtry/catchブロックで発生します。

try {
    OutputStream outputStream = mAppCompatActivity.getContentResolver().openOutputStream(Uri.parse(mUri));
    outputStream.write(mExtendedEditText.getText().toString().getBytes());
    outputStream.close();
    //Toast.makeText(mAppCompatActivity, mAppCompatActivity.getString(R.string.file_updated_confirmation), Toast.LENGTH_SHORT).show();
} catch (IOException e){
    e.printStackTrace();
    dispatchShareEvent();
    Toast.makeText(mAppCompatActivity, mAppCompatActivity.getString(R.string.save_failed), Toast.LENGTH_LONG).show();
    mExtendedEditText.setText(e.toString() + "\n" + exceptionStacktraceToString(e) + "\n\n" + "mUri is " + mUri);
}

具体的には、これは370エラー ログで参照されている行です。

OutputStream outputStream = mAppCompatActivity.getContentResolver().openOutputStream(Uri.parse(mUri));

4

1 に答える 1

2

外部ファイルにアクセスするための、私たちが思いもよらなかった (または作業を行う上でそれほど重要ではないと感じた) インターフェイスを見つけただけだと思います。SD カード パスを処理するようにファイル システムにパッチを適用しますが、使用しようとしたようなコンテンツ Uri を処理するための MediaProvider への変更はありません。

サンプル コード (または少なくともこの投稿へのリンク) を使用してバグを報告してください。他の作業で優先的に修正できるようにします。

于 2015-05-26T22:49:39.473 に答える