7

La mia applicazione utilizza la classe Java RandomAccessFile per leggere/scrivere byte su un file su scheda SD in modo casuale mediante la realizzazione dell'interfaccia SeekableByteChannel. Ora ho bisogno di riscriverlo per Android 5.0 con la nuova API Lollipop.Come arrivare ad accesso casuale in un file su SD-Card per mezzo di API presentate per Lollipop?

ho trovato the only way a leggere:

InputStream inputStream = getContentResolver().openInputStream(uri); 

e scrivere:

ParcelFileDescriptor pfd = getActivity().getContentResolver().openFileDescriptor(uri, "w"); 
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor()); 

da/a un file in nuova API.

Mi piacerebbe avere la possibilità di impostare il canale in alcuni casuale posizione e leggere/scrivere byte in quella posizione. È possibile farlo nel nuovo SDK 21? Ha nuovo SDK implica questo modo ottenimento di canali:

FieInputChannel fieInputChannel = fileInputStream.getChannel(); 
FieOutputChannel fieOutputChannel = fileOutputStream.getChannel(); 

o qualche altro metodo?

risposta

7

Sembra che l'unico modo per ottenere una lettura casuale/scrittura a un file su scheda SD per SDK 21 (Lollipop) è il seguente:

import android.content.Context; 
import android.net.Uri; 
import android.os.ParcelFileDescriptor; 
import com.jetico.bestcrypt.FileManagerApplication; 

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.nio.ByteBuffer; 
import java.nio.channels.FileChannel; 

public class SecondaryCardChannel {//By analogy with the java.nio.channels.SeekableByteChannel 
    private FileChannel fileChannel; 
    private ParcelFileDescriptor pfd; 
    private boolean isInputChannel; 
    private long position; 

    public SecondaryCardChannel(Uri treeUri, Context context) { 
     try { 
      pfd = context.getContentResolver().openFileDescriptor(treeUri, "rw"); 
      FileInputStream fis = new FileInputStream(pfd.getFileDescriptor()); 
      fileChannel = fis.getChannel(); 
      isInputChannel = true; 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 

    public int read(ByteBuffer buffer) { 
     if (!isInputChannel) { 
      try { 
       fileChannel.close(); 
       FileInputStream fis = new FileInputStream(pfd.getFileDescriptor()); 
       fileChannel = fis.getChannel(); 
       isInputChannel = true; 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     try { 
      fileChannel.position(position); 
      int bytesRead = fileChannel.read(buffer); 
      position = fileChannel.position(); 
      return bytesRead; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      return -1; 
     } 
    } 

    public int write(ByteBuffer buffer) { 
     if (isInputChannel) { 
      try { 
       fileChannel.close(); 
       FileOutputStream fos = new FileOutputStream(pfd.getFileDescriptor()); 
       fileChannel = fos.getChannel(); 
       isInputChannel = false; 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     try { 
      fileChannel.position(position); 
      int bytesWrite = fileChannel.write(buffer); 
      position = fileChannel.position(); 
      return bytesWrite; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      return -1; 
     } 
    } 

    public long position() throws IOException { 
     return position; 
    } 

    public SecondaryCardChannel position(long newPosition) throws IOException { 
     position = newPosition; 
     return this; 
    } 

    public long size() throws IOException { 
     return fileChannel.size(); 
    } 

    public SecondaryCardChannel truncate(long size) throws IOException { 
     fileChannel.truncate(size); 
     return this; 
    } 
} 

EDIT 15/03/2017: versione ottimizzata po 'assomiglia

import android.content.Context; 
import android.net.Uri; 
import android.os.ParcelFileDescriptor; 

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.nio.ByteBuffer; 
import java.nio.channels.FileChannel; 

public class SecondaryCardChannel { 
    private ParcelFileDescriptor pfdInput, pfdOutput; 
    private FileInputStream fis; 
    private FileOutputStream fos; 
    private long position; 

    public SecondaryCardChannel(Uri treeUri, Context context) { 
     try { 
      pfdInput = context.getContentResolver().openFileDescriptor(treeUri, "r"); 
      pfdOutput = context.getContentResolver().openFileDescriptor(treeUri, "rw"); 
      fis = new FileInputStream(pfdInput.getFileDescriptor()); 
      fos = new FileOutputStream(pfdOutput.getFileDescriptor()); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 

    public int read(ByteBuffer buffer) { 
     try { 
      FileChannel fch = fis.getChannel(); 
      fch.position(position); 
      int bytesRead = fch.read(buffer); 
      position = fch.position(); 
      return bytesRead; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      return -1; 
     } 
    } 

    public int write(ByteBuffer buffer) { 
     try { 
      FileChannel fch = fos.getChannel(); 
      fch.position(position); 
      int bytesWrite = fch.write(buffer); 
      position = fch.position(); 
      return bytesWrite; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      return -1; 
     } 
    } 

    public long position() throws IOException { 
     return position; 
    } 

    public SecondaryCardChannel position(long newPosition) throws IOException { 
     position = newPosition; 
     return this; 
    } 

    public long size() throws IOException { 
     return fis.getChannel().size(); 
    } 

    public void force(boolean metadata) throws IOException { 
     fos.getChannel().force(metadata); 
     pfdOutput.getFileDescriptor().sync(); 
    } 

    public long truncate(long size) throws Exception { 
     FileChannel fch = fos.getChannel(); 
     try { 
      fch.truncate(size); 
      return fch.size(); 
     } catch (Exception e){ // Attention! Truncate is broken on removable SD card of Android 5.0 
      e.printStackTrace(); 
      return -1; 
     } 
    } 

    public void close() throws IOException { 
     FileChannel fch = fos.getChannel(); 
     fch.close(); 

     fos.close(); 
     fis.close(); 
     pfdInput.close(); 
     pfdOutput.close(); 
    } 
}