2016-06-18 8 views
1

私はオーディオファイルのタグを読み書きするためにJAudioTaggerライブラリを使用しています。私はタグを読むことができますが、タグを書くことはできません。 JAudioTaggerを使用して、タグを記述するためにその後java.io.IOException:ファイルに変更を加えることができません

private String getSongPath(long songId) { 
     String path = null; 
     ContentResolver contentResolver = getContentResolver(); 
     Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 
     String[] projection = {MediaStore.Audio.Media.DATA}; 
     String selection = MediaStore.Audio.Media._ID + " == ?"; 
     String[] selectionArgs = {String.valueOf(songId)}; 

     Cursor cursor = contentResolver.query(uri, projection, selection, selectionArgs, null); 

     if (cursor != null) { 
      int pathCol = cursor.getColumnIndexOrThrow(projection[0]); 
      cursor.moveToFirst(); 
      path = cursor.getString(pathCol); 
      cursor.close(); 
     } 

     return path; 
    } 

:私はこのようなオーディオファイルのパスを取得しています

File songFile = new File(path); // path looks like /storage/3932-3434/Music/xyz.mp3 
AudioFile audiofile = = AudioFileIO.read(songFile); 
Tag tag = = audiofile.getTag(); 
tag.setField(FieldKey.TITLE, title); 
// some more setField calls for different feilds 
audiofile.commit(); 

commit()メソッドは次の例外を与えている:

をorg.jaudiotagger.audio.exceptions.CannotWriteException: java.io.IOException:ファイルを変更できません android.support.v7で com.techapps.musicplayerplus.MainActivity $ 17.onClick(MainActivity.java:2125) で org.jaudiotagger.audio.mp3.MP3File.commit(MP3File.java:799)でxyz.mp3 .app.AlertController $ ButtonHandler.handleMessage(AlertController.java:157) android.os.Handler.dispatchMessage(Handler.java:102)at android.os.Looper.loop(Looper.java:148)at アンドロイド.app.ActivityThread.main(ActivityThread.java:5417)06-18 10:59:48.134 8802-8802/com.techapps.musicplayerplus W/System.err:
at java.lang.reflect.Method.invokeネイティブメソッド) com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:726) at com .android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 原因:java.io.IOException:ファイルSaibo.mp3を変更できません。 org.jaudiotagger.audio.mp3.MP3File.precheck(MP3File .java:824)at org.jaudiotagger.audio.mp3.MP3File.save(MP3File.java:850)at org.jaudiotagger.audio.mp3.MP3File.save(MP3File.java:783)at org.jaudiotagger .audio.mp3.MP3File.commit(MP3File.java:795)

私のアプリは、私もマニフェストで許可次言及しているSDK 22を対象としていながら、私はAndroidの6にこのコードを実行しています。

android.permission.WRITE_EXTERNAL_STORAGE

それでも私は、SDカードへの書き込みをすることができません。私を助けてください。前もって感謝します。

+0

こんにちは!私は同じ問題を抱えています(下記のコメントを読んでください)!あなたがそれを解決したら教えてください! –

答えて

0

既存のファイルが存在しない可能性があります。

ログを使用してパスファイルを確認します。

Log.d("Activity", "path = " + path); 
+0

上記のコードでパスの例を挙げました。 /storage/3932-3434/Music/xyz.mp3のように見えます。私はファイルエクスプローラとそこを介してファイルをチェックしました。 – akshay7692

+0

私は同じ問題を抱えています!私のパスは/storage/6332-6461/Music/xyz.mp3であり、問​​題は数字だと思う。おそらくjaudiotaggerはそれをサポートしていないだろうか?あなたの問題を解決したかどうか教えてください! –

0

Android-MまたはAPI 23は、アンドロイドデバイスのセキュリティ上の欠陥を軽減するためのランタイムアクセス許可を導入しました。

Google Playサービスを使用してAndroid 6.0のアクセス権を処理するアプリを更新するには、ランタイムに必要な権限を設定する際にユーザーの期待を管理することをおすすめします。以下のlinkは潜在的な問題を回避するのに役立ちます。

https://developer.android.com/training/permissions/requesting.html

+0

しかし、私のアプリはAPI 22を対象としているので、AFAIKは実行時の権限は不要で、アプリのインストール時にWRITE_EXTERNAL_STORAGE権限が与えられたときにアプリはうまく動作するはずです。 – akshay7692

0

あなたが許可 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>を宣言していますか?

+0

私は既に上記の許可を宣言していることを私の質問で述べました。 – akshay7692

1

SAF(Storage Access Framework)を使用して、API 19(Kitkat)以降のSDカードにアクセスする必要があります。

  1. まず、アクセスしたいフォルダのURIを入力するようユーザーに依頼する必要があります。 SDカード全体にアクセスしたい場合は、SDカードのルートフォルダのURIを提供する必要があります。 例えば、ユーザーが編集ボタンを押すと、ヒントダイアログボックスが表示され、アクセスしたいSDカード内のディレクトリを選択する必要があります。あなたは、SDカードのルートディレクトリを選択するようユーザーに依頼するヒント]ダイアログボックスで、次の画像を表示することができます。You can use this image in hint dialog box to ask user to select SD Card root directory

  2. ユーザーは、あなたがストレージアクセスフレームワークをトリガするために必要なダイアログボックスをほのめかし解任する場合:

    private void triggerStorageAccessFramework() { 
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); 
    startActivityForResult(intent, REQUEST_CODE_STORAGE_ACCESS); 
    } 
    
    public final void onActivityResult(final int requestCode, final int resultCode, final Intent resultData) { 
    if (resultCode == Activity.RESULT_OK) { 
         if (requestCode == REQUEST_CODE_STORAGE_ACCESS) { 
           Uri treeUri = null; 
           // Get Uri from Storage Access Framework. 
           treeUri = resultData.getData(); 
           pickedDir= DocumentFile.fromTreeUri(this, treeUri); 
    
           if (!isSDCardRootDirectoryUri(treeUri)) { 
            Toast.makeText(this, "Wrong directory selected. Please select SD Card root directory.", Toast.LENGTH_LONG).show(); 
            createSDCardHintDialog().show(); 
            return; 
           }   
    
           // Persist URI in shared preference so that you can use it later.     
           SharedPreferences sharedPreferences = getSharedPreferences(App.PREFERENCE_FILENAME, Context.MODE_PRIVATE); 
           SharedPreferences.Editor editor = sharedPreferences.edit(); 
           editor.putString(App.SDCARD_URI_KEY, treeUri.toString()); 
           editor.apply(); 
    
           // Persist access permissions, so you dont have to ask again 
           final int takeFlags = resultData.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 
           getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 
    
          } 
        } 
    
    private boolean isSDCardRootDirectoryUri(Uri treeUri) { 
        String uriString = treeUri.toString(); 
        return uriString.endsWith("%3A"); 
    } 
    
ユーザー選んだディレクトリのURIを取得したら

、あなたはSAFを使用して、書き込み動作を実行することができます(creadit:this answer

public void writeFile(DocumentFile pickedDir) { 
    try { 
     DocumentFile file = pickedDir.createFile("image/jpeg", "try2.jpg"); 
     OutputStream out = getContentResolver().openOutputStream(file.getUri()); 
     try { 

      // write the image content 

     } finally { 
      out.close(); 
     } 

    } catch (IOException e) { 
     throw new RuntimeException("Something went wrong : " + e.getMessage(), e); 
    } 
} 
関連する問題