Comment obtenir l'URI d'un fichier d'actif?

127

J'ai essayé d'obtenir le chemin URI d'un fichier d'actif.

uri = Uri.fromFile(new File("//assets/mydemo.txt"));

Quand je vérifie si le fichier existe, je vois que ce fichier n'existe pas

File f = new File(filepath);
if (f.exists() == true) {
    Log.e(TAG, "Valid :" + filepath);
} else {
    Log.e(TAG, "InValid :" + filepath);
}

Quelqu'un peut-il me dire comment je peux mentionner le chemin absolu d'un fichier existant dans le dossier d'actifs

Titus
la source

Réponses:

160

Il n'y a pas de "chemin absolu pour un fichier existant dans le dossier de ressources". Le contenu du assets/dossier de votre projet est emballé dans le fichier APK. Utilisez un AssetManagerobjet pour obtenir un InputStreamsur un actif.

Pour WebView, vous pouvez utiliser le file Urischéma de la même manière que vous utiliseriez une URL. La syntaxe des actifs est file:///android_asset/...(note: trois barres obliques) où les points de suspension sont le chemin du fichier à partir du assets/dossier.

CommonsWare
la source
32
file://android_asset/..., où ...est le chemin relatif dans le assets/répertoire de votre projet .
CommonsWare
4
Voici un exemple de projet à l' aide file://android_asset/, mais pas pour Uri: github.com/commonsguy/cw-advandroid/tree/master/WebView/GeoWeb1
CommonsWare
20
@CommonsWare, il semble que vous ayez manqué un «/» dans votre URI. Ça devrait être file:///.
ThomasW
7
J'ai essayé ceci comme new File("file:///android_asset/sounds/beep.mid");, mais le fichier de résultat n'existe pas. Des idées? Le fichier PS est dans le assets/sounds/dossier.
oncle Lem
3
Est-il vrai que «file: ///android_asset/... »ne fonctionne que dans WebView et n'est pas possible d'obtenir InputStream en utilisant URI / URL / Uri en dehors de WebView?
Lubbo
74

L'URL correcte est:

file:///android_asset/RELATIVEPATH

où RELATIVEPATH est le chemin d'accès à votre ressource par rapport au dossier des actifs.

Notez les 3 / dans le schéma. La vue Web ne chargerait aucun de mes actifs sans le 3. J'ai essayé 2 comme (précédemment) commenté par CommonsWare et cela ne fonctionnerait pas. Ensuite, j'ai regardé la source de CommonsWare sur github et j'ai remarqué la barre oblique supplémentaire.

Ce test n'a cependant été effectué que sur l'émulateur Android 1.6, mais je doute que ce soit différent sur un appareil réel ou une version supérieure.

EDIT: CommonsWare a mis à jour sa réponse pour refléter ce petit changement. J'ai donc édité ceci pour que cela ait toujours du sens avec sa réponse actuelle.

Russ
la source
Ne fonctionne plus String fileName = "file:///android_asset/file.csv"; System.out.println(new File(fileName).exists()); // prints false
Elgirhath
@Elgirhath le constructeur pour Filequi accepte une chaîne attend un chemin pas un URI . Je n'ai pas codé pour Android depuis quelques années et les choses ont peut-être changé. Je ne sais pas si vous pouvez accéder au dossier des actifs intégrés à l'aide d'une classe de fichier Java normale. Il me semble que vous devez utiliser un AssetManager . Les fichiers dans le dossier des ressources sont placés sur l'appareil dans l'APK en lecture seule et compressés (les APK sont en fait des fichiers zip), donc plus de travail pour le relire. Essayez quelque chose commenew File(new URI(filename))
Russ
10

Veuillez essayer que ce code fonctionne correctement

 Uri imageUri = Uri.fromFile(new File("//android_asset/luc.jpeg"));

    /* 2) Create a new Intent */
    Intent imageEditorIntent = new AdobeImageIntent.Builder(this)
            .setData(imageUri)
            .build();
Raaz Thakur
la source
8

Enfin, j'ai trouvé un moyen d'obtenir le chemin d'un fichier présent dans les actifs à partir de cette réponse dans Kotlin. Ici, nous copions le fichier de ressources dans le cache et obtenons le chemin du fichier à partir de ce fichier de cache.

@Throws(IOException::class)
    fun getFileFromAssets(context: Context, fileName: String): File = File(context.cacheDir, fileName)
            .also {
               if (!it.exists()) {
                it.outputStream().use { cache ->
                    context.assets.open(fileName).use { inputStream ->
                            inputStream.copyTo(cache)
                    }
                  }
                }
            }

Obtenez le chemin d'accès au fichier comme:

val filePath =  getFileFromAssets(context, "fileName.extension").absolutePath
Shylendra Madda
la source
1
Notez que si le fileNamerépertoire have dir/file. Il plantera avec le chemin qui cache/dir/filen'existe pas. Aussi, je pense qu'il vaut mieux avoir une vérification if(!it.exist)à l'intérieur du alsobloc, alors il ne copiera pas le fichier à chaque fois que même le fichier est déjà sur le cache
Yeung
@ShylendraMadda, @Yeung, if(!it.exist)lance une référence d'erreur non résolue. Toute solution ?
binrebin
Vérifiez que le fichier existe dans votre cache avec ce nom de fichier? @binrebin
Shylendra Madda
@ShylendraMadda, je ne connais que le nom du fichier. Pouvons-nous le charger avec un script sans connaître l'
URI
Je pense qu'il if(!it.exist)faudrait mettre avant it.outputStream()...
Yeung
7

entrez la description de l'image ici

Assurez-vous que votre dossier de ressources est placé dans la bonne position.

Chuanhang.gu
la source
Vous pouvez le mettre où vous voulez et définir le chemin dans votre fichier build.gradle comme suitsourceSets { main { assets.srcDirs = ['src/main/assets'] } }
Marcel Bro
2
Comment obtenir le chemin de hello.html? s'il vous plaît ajouter
Rohit Singh
6

Fonctionne pour WebView mais semble échouer URL.openStream(). Vous devez donc distinguer les protocoles file: // et les gérer via AssetManager comme suggéré.

Gaylord Zach
la source
4

Essayez ceci, cela fonctionne:

InputStream in_s = 
    getClass().getClassLoader().getResourceAsStream("TopBrands.xml");

Si vous obtenez une exception de valeur nulle, essayez ceci (avec classe TopBrandData):

InputStream in_s1 =
    TopBrandData.class.getResourceAsStream("/assets/TopBrands.xml");
Jaspreet Singh
la source
Si cela ne fonctionne pas, veuillez essayer celui-ci: InputStream in_s1 = TopBrandData.class.getResourceAsStream ("/ assets / TopBrands.xml");
Jaspreet Singh
3
InputStream is = getResources().getAssets().open("terms.txt");
String textfile = convertStreamToString(is);
    
public static String convertStreamToString(InputStream is)
        throws IOException {

    Writer writer = new StringWriter();
    char[] buffer = new char[2048];

    try {
        Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        int n;
        while ((n = reader.read(buffer)) != -1) {
            writer.write(buffer, 0, n);
        }
    } finally {
        is.close();
    }

    String text = writer.toString();
    return text;
}
Jayesh Kavathiya
la source
1

essaye ça :

Uri uri = Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.cat); 

Je l'avais fait et ça a marché

Nyle
la source
2
En fait ça marche. Vérifier ContentResolver.openAssetFileDescriptor
Hippo Seven
1
Travaillé. Merci beaucoup. Lol, je cherche juste à obtenir le fichier interne de l'URI // CRÉER UN DOSSIER RAW À L'INTÉRIEUR DE RES, PUIS LE FICHIER DE NOM CONTIENT UNIQUEMENT UN caractère..z0..9, PAS DE MAJUSCULES !!!
phnghue le
0

Oui, vous ne pouvez pas accéder à votre dossier de lecteur à partir de votre téléphone ou de votre émulateur Android, car votre ordinateur et Android sont deux systèmes d'exploitation différents.Je choisirais le dossier res d'Android car il dispose de bonnes méthodes de gestion des ressources. Jusqu'à et à moins que vous n'ayez de très bonnes raisons de placer votre fichier dans le dossier des actifs. Au lieu de cela, vous pouvez le faire

try {
      Resources res = getResources();
      InputStream in_s = res.openRawResource(R.raw.yourfile);

      byte[] b = new byte[in_s.available()];
      in_s.read(b);
      String str = new String(b);
    } catch (Exception e) {
      Log.e(LOG_TAG, "File Reading Error", e);
 }
ne quittera pas
la source
-7

A travaillé pour moi Essayez ce code

   uri = Uri.fromFile(new File("//assets/testdemo.txt"));
   String testfilepath = uri.getPath();
    File f = new File(testfilepath);
    if (f.exists() == true) {
    Toast.makeText(getApplicationContext(),"valid :" + testfilepath, 2000).show();
    } else {
   Toast.makeText(getApplicationContext(),"invalid :" + testfilepath, 2000).show();
 }
Irfan Ali
la source