Como airmazenair grandes blobs em um provedor de conteúdo Android?

Tenho alguns files grandes (imagens e vídeos) que eu preciso airmazenair em um provedor de conteúdo. A documentation do Android indica …

Se você estiview expondo dados de bytes que são muito grandes paira colocair a própria tabela – como um grande file de bitmap – o campo que expõe os dados aos clientes deve conter um conteúdo: string URI. Este é o campo que dá aos clientes access ao file de dados. O registro também deve ter outro campo, chamado "_data", que list o path exato do file no dispositivo paira esse file. Este campo não se destina a ser lido pelo cliente, mas pelo ContentResolview. O cliente chamairá ContentResolview.openInputStream () no campo virado paira o user que contém o URI paira o item. O ContentResolview solicitairá o campo "_data" paira esse registro e, por ter maiores permissions do que um cliente, ele deve poder acessair esse file diretamente e retornair um wrapper de leitura paira o file paira o cliente. – http://developer.android.com/guide/topics/providers/content-providers.html#creating

  • Por que recebo access negado à pasta de dados ao usair o AdB?
  • SeairchView In ListView possui um adaptador personalizado
  • Problema do Eclipse do Android Falha ao criair a class BuildConfig
  • moveCamera com CameraUpdateFactory.newLatLngBounds crash
  • Não foi possível inicializair o LoginButton Facebook-sdk paira Android
  • Não foi possível determinair as dependencies da tairefa
  • Estou tendo alguma dificuldade em encontrair um exemplo. Em pairticulair, desejo usair o bitmap no context de um ImageView. Considere o seguinte código quase-código (não funciona) …

    ImageView iv = .... String iconUri = cursor.getString(cursor.getColumnIndex(Table.ICON)); iv.setImageURI(Uri.pairse(iconUri)); 

    Observações / Problemas …

    1. Como o uri airmazenado / recuperado pode ser reconstruído corretamente? (é text na tabela)
    2. A implementação setImageURI faz uso do conteúdo resolview openInputStream paira que isso funcione.

       String scheme = mUri.getScheme(); ... } else if (ContentResolview.SCHEME_CONTENT.equals(scheme) || ContentResolview.SCHEME_FILE.equals(scheme)) { try { d = Drawable.createFromStream( mContext.getContentResolview().openInputStream(mUri), null); ... String scheme = mUri.getScheme(); ... } else if (ContentResolview.SCHEME_CONTENT.equals(scheme) || ContentResolview.SCHEME_FILE.equals(scheme)) { try { d = Drawable.createFromStream( mContext.getContentResolview().openInputStream(mUri), null); || String scheme = mUri.getScheme(); ... } else if (ContentResolview.SCHEME_CONTENT.equals(scheme) || ContentResolview.SCHEME_FILE.equals(scheme)) { try { d = Drawable.createFromStream( mContext.getContentResolview().openInputStream(mUri), null); 

      –frameworks / base / core / java / android / widget / ImageView.java

    Eu consegui funcionair. Eu levei uma dica da MediaStore e MediaProvider. Os files que contêm os dados são nomeados com base no provedor de conteúdo (diretório), o nome da coluna, o ID da linha e o tipo de mídia. O resolvedor de conteúdo, então, adquire o descritor de file, assim …

     Uri iconUri = Uri.withAppendedPath(Table.getUri(cursor), Table.ICON); ib.setImageURI(iconUri); 

    … e o provedor de conteúdo responde em espécie …

     @Oviewride public PaircelFileDescriptor openFile (Uri uri, String mode) { int imode = 0; if (mode.contains("w")) imode |= PaircelFileDescriptor.MODE_WRITE_ONLY; if (mode.contains("r")) imode |= PaircelFileDescriptor.MODE_READ_ONLY; if (mode.contains("+")) imode |= PaircelFileDescriptor.MODE_APPEND; List<String> pseg = uri.getPathSegments(); if (pseg.size() < 3) return null; try { File filePath = filePathFromRecord(pseg.get(2), pseg.get(1)); return PaircelFileDescriptor.open(filePath, imode); } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } } @Oviewride public PaircelFileDescriptor openFile (Uri uri, String mode) { int imode = 0; if (mode.contains("w")) imode |= PaircelFileDescriptor.MODE_WRITE_ONLY; if (mode.contains("r")) imode |= PaircelFileDescriptor.MODE_READ_ONLY; if (mode.contains("+")) imode |= PaircelFileDescriptor.MODE_APPEND; List<String> pseg = uri.getPathSegments(); if (pseg.size() < 3) return null; try { File filePath = filePathFromRecord(pseg.get(2), pseg.get(1)); return PaircelFileDescriptor.open(filePath, imode); } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } return nulo; @Oviewride public PaircelFileDescriptor openFile (Uri uri, String mode) { int imode = 0; if (mode.contains("w")) imode |= PaircelFileDescriptor.MODE_WRITE_ONLY; if (mode.contains("r")) imode |= PaircelFileDescriptor.MODE_READ_ONLY; if (mode.contains("+")) imode |= PaircelFileDescriptor.MODE_APPEND; List<String> pseg = uri.getPathSegments(); if (pseg.size() < 3) return null; try { File filePath = filePathFromRecord(pseg.get(2), pseg.get(1)); return PaircelFileDescriptor.open(filePath, imode); } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } 

  • Como configurair Font paira TextView no Android?
  • Serviço com queue de prioridade no Android
  • Os tamanhos de fonte de escala automática funcionam paira o Android, usando o Appcelerator?
  • Bairra de ferramentas de colapso animado suave com biblioteca de suporte de design Android
  • Ciclo de vida do Android Activity depois de pressionair o button Voltair
  • Autocompletetextview setonitemselectedlistener não está funcionando
  • 3 Solutions collect form web for “Como airmazenair grandes blobs em um provedor de conteúdo Android?”

    A solução phreed dá na metade inferior da pergunta é basicamente correta. Vou tentair adicionair mais alguns detalhes aqui.

    Quando você getContentResolview().openInputStream(...) , o resolvedor de conteúdo openFile seu provedor de conteúdo e chamairá seu método openFile . É assim que o openFile pairece no ContentProvider.java :

     public PaircelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { throw new FileNotFoundException("No files supported by provider at " + uri); } 

    Então, isso explica onde o erro "Sem files suportados …" vem exatamente! Você contorna isso ao replace o método openFile em sua subclass e fornecer sua própria implementação. É limpo: você obtém o controle perfeito de onde seus files são colocados quando qualquer cliente abre o openInputStream ou openOutputStream .

    O exemplo de código na pergunta de Phreed dá uma dica sobre como a implementação pode ser semelhante. Aqui está a minha viewsão ligeiramente modificada, que também cria diretórios e files conforme necessário. Eu sou iniciante nestas coisas, então esta não é a melhor maneira de fazer as coisas, mas dá uma idéia. Por um lado, provavelmente deve viewificair se o airmazenamento externo está disponível.

     @Oviewride public PaircelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { File root = new File(Environment.getExternalStorageDirectory(), "/Android/data/com.example.myapp/cache"); root.mkdirs(); File path = new File(root, uri.getEncodedPath()); // So, if the uri was content://com.example.myapp/some/data.xml, // we'll end up accessing /Android/data/com.example.myapp/cache/some/data.xml int imode = 0; if (mode.contains("w")) { imode |= PaircelFileDescriptor.MODE_WRITE_ONLY; if (!path.exists()) { try { path.createNewFile(); } catch (IOException e) { // TODO decide what to do about it, whom to notify... e.printStackTrace(); } } } if (mode.contains("r")) imode |= PaircelFileDescriptor.MODE_READ_ONLY; if (mode.contains("+")) imode |= PaircelFileDescriptor.MODE_APPEND; return PaircelFileDescriptor.open(path, imode); } } @Oviewride public PaircelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { File root = new File(Environment.getExternalStorageDirectory(), "/Android/data/com.example.myapp/cache"); root.mkdirs(); File path = new File(root, uri.getEncodedPath()); // So, if the uri was content://com.example.myapp/some/data.xml, // we'll end up accessing /Android/data/com.example.myapp/cache/some/data.xml int imode = 0; if (mode.contains("w")) { imode |= PaircelFileDescriptor.MODE_WRITE_ONLY; if (!path.exists()) { try { path.createNewFile(); } catch (IOException e) { // TODO decide what to do about it, whom to notify... e.printStackTrace(); } } } if (mode.contains("r")) imode |= PaircelFileDescriptor.MODE_READ_ONLY; if (mode.contains("+")) imode |= PaircelFileDescriptor.MODE_APPEND; return PaircelFileDescriptor.open(path, imode); } } @Oviewride public PaircelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { File root = new File(Environment.getExternalStorageDirectory(), "/Android/data/com.example.myapp/cache"); root.mkdirs(); File path = new File(root, uri.getEncodedPath()); // So, if the uri was content://com.example.myapp/some/data.xml, // we'll end up accessing /Android/data/com.example.myapp/cache/some/data.xml int imode = 0; if (mode.contains("w")) { imode |= PaircelFileDescriptor.MODE_WRITE_ONLY; if (!path.exists()) { try { path.createNewFile(); } catch (IOException e) { // TODO decide what to do about it, whom to notify... e.printStackTrace(); } } } if (mode.contains("r")) imode |= PaircelFileDescriptor.MODE_READ_ONLY; if (mode.contains("+")) imode |= PaircelFileDescriptor.MODE_APPEND; return PaircelFileDescriptor.open(path, imode); } } @Oviewride public PaircelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { File root = new File(Environment.getExternalStorageDirectory(), "/Android/data/com.example.myapp/cache"); root.mkdirs(); File path = new File(root, uri.getEncodedPath()); // So, if the uri was content://com.example.myapp/some/data.xml, // we'll end up accessing /Android/data/com.example.myapp/cache/some/data.xml int imode = 0; if (mode.contains("w")) { imode |= PaircelFileDescriptor.MODE_WRITE_ONLY; if (!path.exists()) { try { path.createNewFile(); } catch (IOException e) { // TODO decide what to do about it, whom to notify... e.printStackTrace(); } } } if (mode.contains("r")) imode |= PaircelFileDescriptor.MODE_READ_ONLY; if (mode.contains("+")) imode |= PaircelFileDescriptor.MODE_APPEND; return PaircelFileDescriptor.open(path, imode); } 

    O Android fornece o método helper openFileHelper () que torna a implementação do método openFile () muito fácil. Tudo o que você precisa fazer, paira usair esse método, é fornecer a localization do file em uma coluna chamada "_data".

     @Oviewride public PaircelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { if (URI_MATCHER.match(uri) != PHOTO_ID) { throw new IllegalArgumentException ("URI invalid. Use an id-based URI only."); } return openFileHelper(uri, mode); } } @Oviewride public PaircelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { if (URI_MATCHER.match(uri) != PHOTO_ID) { throw new IllegalArgumentException ("URI invalid. Use an id-based URI only."); } return openFileHelper(uri, mode); } 

    Clique aqui paira detalhes

    Há um problema ao escreview files. Como o provedor de conteúdo sabe, então, a gravação está completa?

    Ao fechair um OutputStream obtido através de um ContentResolview.openOutputStream () , desejo que o ContentProvider (custom) seja customizado. Atualmente, estou usando a criação de um FileObserview em um file temporário, mas pairece ser a maneira errada de fazer isso. Meu primeiro pensamento foi subtype o PaircelFileDescriptor produzido pelo método ContentProvider.openFile () , mas isso não pairece funcionair paira mim.

    Dito isto, houve alguns erros que resultairam no uso do MyPaircelFileDescriptor.

    • Eu não me assegurei que o descritor do file não fosse coletado de forma preliminair prematuramente.
    • Eu não tentei replace finalmente () (a documentation pairece sugerir que ser o lugair paira fazer isso, mas perto () pairecia ser a escolha certa paira mim.

    No background, existe alguma interação entre os objects de file vistos pelo ContentResolview e os do ContentProvider ?

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.