Dosyalar 'varlıklar' klasöründen sdcard'a nasıl kopyalanır?


250

assetsKlasörde birkaç dosya var . Hepsini say / sdcard / klasörüne bir klasöre kopyalamam gerekiyor. Bunu bir iş parçacığı içinde yapmak istiyorum. Nasıl yaparım?



2
Aşağıdaki (harika!) Çözümlerden birini kopyalama / yapıştırmadan önce, bu kütüphaneyi bir kod satırında yapmak için kullanmayı düşünün: stackoverflow.com/a/41970539/9648
JohnnyLambada

Yanıtlar:


345

Başka biri aynı sorunu yaşıyorsa, ben böyle yaptım

private void copyAssets() {
    AssetManager assetManager = getAssets();
    String[] files = null;
    try {
        files = assetManager.list("");
    } catch (IOException e) {
        Log.e("tag", "Failed to get asset file list.", e);
    }
    if (files != null) for (String filename : files) {
        InputStream in = null;
        OutputStream out = null;
        try {
          in = assetManager.open(filename);
          File outFile = new File(getExternalFilesDir(null), filename);
          out = new FileOutputStream(outFile);
          copyFile(in, out);
        } catch(IOException e) {
            Log.e("tag", "Failed to copy asset file: " + filename, e);
        }     
        finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    // NOOP
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    // NOOP
                }
            }
        }  
    }
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
    byte[] buffer = new byte[1024];
    int read;
    while((read = in.read(buffer)) != -1){
      out.write(buffer, 0, read);
    }
}

Başvuru: Dosyayı Java kullanarak taşıma


28
sdcard dosya yazmak için manifest üzerinde izin vermek zorunda örneğin <kullanımları-izin android: adı = "android.permission.WRITE_EXTERNAL_STORAGE" />
IronBlossom 18:12

22
Ben de sdcard / sdcard bulunan güvenmek olmaz, ancak Environment.getExternalStorageDirectory ()
Axarydax 21:12

2
Kullanmalı mıyım: 16 * 1024 (16kb) Bellek kullanımı ve performansı arasında iyi bir denge olarak 16K veya 32K tercih etme eğilimindeyim.
Nam Vu

3
@rciovati bu çalışma zamanı hatasını aldıFailed to copy asset file: myfile.txt java.io.FileNotFoundException: myfile.txt at android.content.res.AssetManager.openAsset(Native Method)
likejudo

7
Benim için bu kod yalnızca bunu eklerseniz çalışır: in = assetManager.open("images-wall/"+filename);Burada "görüntüler-duvar" varlıklar içindeki
klasörüm

62

Çözümünüze dayanarak, alt klasörlere izin vermek için kendime ait bir şey yaptım. Birisi bunu faydalı bulabilir:

...

copyFileOrDir("myrootdir");

...

private void copyFileOrDir(String path) {
    AssetManager assetManager = this.getAssets();
    String assets[] = null;
    try {
        assets = assetManager.list(path);
        if (assets.length == 0) {
            copyFile(path);
        } else {
            String fullPath = "/data/data/" + this.getPackageName() + "/" + path;
            File dir = new File(fullPath);
            if (!dir.exists())
                dir.mkdir();
            for (int i = 0; i < assets.length; ++i) {
                copyFileOrDir(path + "/" + assets[i]);
            }
        }
    } catch (IOException ex) {
        Log.e("tag", "I/O Exception", ex);
    }
}

private void copyFile(String filename) {
    AssetManager assetManager = this.getAssets();

    InputStream in = null;
    OutputStream out = null;
    try {
        in = assetManager.open(filename);
        String newFileName = "/data/data/" + this.getPackageName() + "/" + filename;
        out = new FileOutputStream(newFileName);

        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
    } catch (Exception e) {
        Log.e("tag", e.getMessage());
    }

}

1
assetManager.list(path)cihazda yavaş olabilir, önceden varlık yolları listesi oluşturmak için bu pasaj şu adresten kullanılabilir assets:find . -name "*" -type f -exec ls -l {} \; | awk '{print substr($9,3)}' >> assets.list
alexkasko

3
Güzel çözüm! Gereken tek düzeltme, önde gelen ayırıcıları copyFileOrDir () öğesinin başında kırpmaktır: path = path.startsWith ("/")? path.substring (1): yol;
Cross_


2
"/ data / data /" +
this.getPackageName

1
... ve finallybloktaki akışları kapatın ))
Mixaz

48

Yukarıdaki çözüm bazı hatalar nedeniyle işe yaramadı:

  • dizin oluşturma işe yaramadı
  • Android tarafından döndürülen öğeler ayrıca üç klasör içerir: resimler, sesler ve webkit
  • Büyük dosyalarla başa çıkmanın yolu eklendi: Projenizdeki öğeler klasöründeki dosyaya .mp3 uzantısı ekleyin ve kopyalama sırasında hedef dosya .mp3 uzantısı olmadan olacaktır

İşte kod (Log deyimlerini bıraktım, ancak şimdi bırakabilirsiniz):

final static String TARGET_BASE_PATH = "/sdcard/appname/voices/";

private void copyFilesToSdCard() {
    copyFileOrDir(""); // copy all files in assets folder in my project
}

private void copyFileOrDir(String path) {
    AssetManager assetManager = this.getAssets();
    String assets[] = null;
    try {
        Log.i("tag", "copyFileOrDir() "+path);
        assets = assetManager.list(path);
        if (assets.length == 0) {
            copyFile(path);
        } else {
            String fullPath =  TARGET_BASE_PATH + path;
            Log.i("tag", "path="+fullPath);
            File dir = new File(fullPath);
            if (!dir.exists() && !path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
                if (!dir.mkdirs())
                    Log.i("tag", "could not create dir "+fullPath);
            for (int i = 0; i < assets.length; ++i) {
                String p;
                if (path.equals(""))
                    p = "";
                else 
                    p = path + "/";

                if (!path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
                    copyFileOrDir( p + assets[i]);
            }
        }
    } catch (IOException ex) {
        Log.e("tag", "I/O Exception", ex);
    }
}

private void copyFile(String filename) {
    AssetManager assetManager = this.getAssets();

    InputStream in = null;
    OutputStream out = null;
    String newFileName = null;
    try {
        Log.i("tag", "copyFile() "+filename);
        in = assetManager.open(filename);
        if (filename.endsWith(".jpg")) // extension was added to avoid compression on APK file
            newFileName = TARGET_BASE_PATH + filename.substring(0, filename.length()-4);
        else
            newFileName = TARGET_BASE_PATH + filename;
        out = new FileOutputStream(newFileName);

        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
    } catch (Exception e) {
        Log.e("tag", "Exception in copyFile() of "+newFileName);
        Log.e("tag", "Exception in copyFile() "+e.toString());
    }

}

EDIT: Yanlış yerleştirilmiş bir ";" düzeltildi sistematik bir "dir oluşturulamadı" hatası atıyordu.


4
bu çözüm olmalı!
Massimo Variolo

1
Not: Log.i ("tag", "dir" + fullPath oluşturulamadı); her zaman şöyle olur; durumunda yanlış yerleştirilir.
RoundSparrow hilltx

muhteşem bir yol! Çok teşekkürler! Ama neden jpg dosyasını kontrol ediyorsunuz?
Phuong

32

Bunun cevaplandığını biliyorum ama varlık dizininden sdcard'daki bir dosyaya kopyalamak için biraz daha zarif bir yolum var. Hiçbir "for" döngüsü gerektirmez, bunun yerine işi yapmak için Dosya Akışları ve Kanalları kullanır.

(Not) Herhangi bir sıkıştırılmış dosya, APK, PDF, ... kullanıyorsanız, öğeye eklemeden önce dosya uzantısını yeniden adlandırmak ve daha sonra SDcard'a kopyaladıktan sonra yeniden adlandırmak isteyebilirsiniz)

AssetManager am = context.getAssets();
AssetFileDescriptor afd = null;
try {
    afd = am.openFd( "MyFile.dat");

    // Create new file to copy into.
    File file = new File(Environment.getExternalStorageDirectory() + java.io.File.separator + "NewFile.dat");
    file.createNewFile();

    copyFdToFile(afd.getFileDescriptor(), file);

} catch (IOException e) {
    e.printStackTrace();
}

Bir dosyayı döngü içinde dolaşmak zorunda kalmadan kopyalamanın bir yolu.

public static void copyFdToFile(FileDescriptor src, File dst) throws IOException {
    FileChannel inChannel = new FileInputStream(src).getChannel();
    FileChannel outChannel = new FileOutputStream(dst).getChannel();
    try {
        inChannel.transferTo(0, inChannel.size(), outChannel);
    } finally {
        if (inChannel != null)
            inChannel.close();
        if (outChannel != null)
            outChannel.close();
    }
}

Diğer çözümler, biraz daha temiz bunu sevdim. Eksik fileFolders oluşturmayı içeren mayın üzerinde hafif değişiklik. şerefe!
Chris.Jenkins

3
Bu benim için dosya tanımlayıcı geçmiş işe yaramaz, This file can not be opened as a file descriptor; it is probably compressed- bu bir pdf dosyası. Bunu nasıl düzeltebileceğinizi biliyor musunuz?
Gaʀʀʏ

1
Bu, inChannel.size () öğesinin dosya boyutunun boyutunu döndürdüğünü varsayar. Bu kılan böyle bir garanti . Her biri 450 KiB olan 2 dosya için 2.5 MiB alıyorum.
AI0867

1
Ben sadece AssetFileDescriptor.getLength () doğru dosya boyutu döndürecek bulduk.
AI0867

1
Yukarıdakilere ek olarak, varlık dosya tanımlayıcısında 0 konumunda başlamayabilir. AssetFileDescriptor.getStartOffset () başlangıç ​​ofsetini döndürür.
AI0867

5

bunu deneyin çok daha basit, bu u yardımcı olacaktır:

// Open your local db as the input stream
    InputStream myInput = _context.getAssets().open(YOUR FILE NAME);

    // Path to the just created empty db
    String outFileName =SDCARD PATH + YOUR FILE NAME;

    // Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    // transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }
    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();

5

Kotlin'de bu çok kısa bir yol olurdu.

    fun AssetManager.copyRecursively(assetPath: String, targetFile: File) {
        val list = list(assetPath)
        if (list.isEmpty()) { // assetPath is file
            open(assetPath).use { input ->
                FileOutputStream(targetFile.absolutePath).use { output ->
                    input.copyTo(output)
                    output.flush()
                }
            }

        } else { // assetPath is folder
            targetFile.delete()
            targetFile.mkdir()

            list.forEach {
                copyRecursively("$assetPath/$it", File(targetFile, it))
            }
        }
    }

list (assetPath)?. izin verin {...}. Null edilebilir.
Gábor

4

İşte mevcut Android cihazlar için temizlenmiş bir sürüm, fonksiyonel yöntem tasarımı, böylece bir AssetsHelper sınıfına kopyalayabilirsiniz;)

/**
 * 
 * Info: prior to Android 2.3, any compressed asset file with an
 * uncompressed size of over 1 MB cannot be read from the APK. So this
 * should only be used if the device has android 2.3 or later running!
 * 
 * @param c
 * @param targetFolder
 *            e.g. {@link Environment#getExternalStorageDirectory()}
 * @throws Exception
 */
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public static boolean copyAssets(AssetManager assetManager,
        File targetFolder) throws Exception {
    Log.i(LOG_TAG, "Copying files from assets to folder " + targetFolder);
    return copyAssets(assetManager, "", targetFolder);
}

/**
 * The files will be copied at the location targetFolder+path so if you
 * enter path="abc" and targetfolder="sdcard" the files will be located in
 * "sdcard/abc"
 * 
 * @param assetManager
 * @param path
 * @param targetFolder
 * @return
 * @throws Exception
 */
public static boolean copyAssets(AssetManager assetManager, String path,
        File targetFolder) throws Exception {
    Log.i(LOG_TAG, "Copying " + path + " to " + targetFolder);
    String sources[] = assetManager.list(path);
    if (sources.length == 0) { // its not a folder, so its a file:
        copyAssetFileToFolder(assetManager, path, targetFolder);
    } else { // its a folder:
        if (path.startsWith("images") || path.startsWith("sounds")
                || path.startsWith("webkit")) {
            Log.i(LOG_TAG, "  > Skipping " + path);
            return false;
        }
        File targetDir = new File(targetFolder, path);
        targetDir.mkdirs();
        for (String source : sources) {
            String fullSourcePath = path.equals("") ? source : (path
                    + File.separator + source);
            copyAssets(assetManager, fullSourcePath, targetFolder);
        }
    }
    return true;
}

private static void copyAssetFileToFolder(AssetManager assetManager,
        String fullAssetPath, File targetBasePath) throws IOException {
    InputStream in = assetManager.open(fullAssetPath);
    OutputStream out = new FileOutputStream(new File(targetBasePath,
            fullAssetPath));
    byte[] buffer = new byte[16 * 1024];
    int read;
    while ((read = in.read(buffer)) != -1) {
        out.write(buffer, 0, read);
    }
    in.close();
    out.flush();
    out.close();
}

4

@DannyA tarafından bu SO yanıtı değiştirildi

private void copyAssets(String path, String outPath) {
    AssetManager assetManager = this.getAssets();
    String assets[];
    try {
        assets = assetManager.list(path);
        if (assets.length == 0) {
            copyFile(path, outPath);
        } else {
            String fullPath = outPath + "/" + path;
            File dir = new File(fullPath);
            if (!dir.exists())
                if (!dir.mkdir()) Log.e(TAG, "No create external directory: " + dir );
            for (String asset : assets) {
                copyAssets(path + "/" + asset, outPath);
            }
        }
    } catch (IOException ex) {
        Log.e(TAG, "I/O Exception", ex);
    }
}

private void copyFile(String filename, String outPath) {
    AssetManager assetManager = this.getAssets();

    InputStream in;
    OutputStream out;
    try {
        in = assetManager.open(filename);
        String newFileName = outPath + "/" + filename;
        out = new FileOutputStream(newFileName);

        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
        in.close();
        out.flush();
        out.close();
    } catch (Exception e) {
        Log.e(TAG, e.getMessage());
    }

}

Hazırlıklar

içinde src/main/assets adı ile eklenti klasörünefold

kullanım

File outDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString());
copyAssets("fold",outDir.toString());

Dış dizinde, fold varlıkları içindeki tüm dosya ve dizinleri bulun


3

Varlıklardan tüm dosya ve dizinleri klasörünüze kopyalayın!

kopyalamak için daha iyi kullanın apache commons io

public void doCopyAssets() throws IOException {
    File externalFilesDir = context.getExternalFilesDir(null);

    doCopy("", externalFilesDir.getPath());

}

// BU KOPYA İÇİN ANA YÖNTEM

private void doCopy(String dirName, String outPath) throws IOException {

    String[] srcFiles = assets.list(dirName);//for directory
    for (String srcFileName : srcFiles) {
        String outFileName = outPath + File.separator + srcFileName;
        String inFileName = dirName + File.separator + srcFileName;
        if (dirName.equals("")) {// for first time
            inFileName = srcFileName;
        }
        try {
            InputStream inputStream = assets.open(inFileName);
            copyAndClose(inputStream, new FileOutputStream(outFileName));
        } catch (IOException e) {//if directory fails exception
            new File(outFileName).mkdir();
            doCopy(inFileName, outFileName);
        }

    }
}

public static void closeQuietly(AutoCloseable autoCloseable) {
    try {
        if(autoCloseable != null) {
            autoCloseable.close();
        }
    } catch(IOException ioe) {
        //skip
    }
}

public static void copyAndClose(InputStream input, OutputStream output) throws IOException {
    copy(input, output);
    closeQuietly(input);
    closeQuietly(output);
}

public static void copy(InputStream input, OutputStream output) throws IOException {
    byte[] buffer = new byte[1024];
    int n = 0;
    while(-1 != (n = input.read(buffer))) {
        output.write(buffer, 0, n);
    }
}

2

Yoram Cohen yanıtına dayanarak, statik olmayan hedef dizini destekleyen bir sürüm.

İle Invoque copyFileOrDir(getDataDir(), "")için yazma için dahili uygulama depolama klasör / veri / data / pkg_name /

  • Alt klasörleri destekler.
  • Özel ve statik olmayan hedef dizini destekler
  • "Resimler" vb. Gibi sahte varlık klasörlerinin kopyalanmasını önler

    private void copyFileOrDir(String TARGET_BASE_PATH, String path) {
    AssetManager assetManager = this.getAssets();
    String assets[] = null;
    try {
        Log.i("tag", "copyFileOrDir() "+path);
        assets = assetManager.list(path);
        if (assets.length == 0) {
            copyFile(TARGET_BASE_PATH, path);
        } else {
            String fullPath =  TARGET_BASE_PATH + "/" + path;
            Log.i("tag", "path="+fullPath);
            File dir = new File(fullPath);
            if (!dir.exists() && !path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
                if (!dir.mkdirs())
                    Log.i("tag", "could not create dir "+fullPath);
            for (int i = 0; i < assets.length; ++i) {
                String p;
                if (path.equals(""))
                    p = "";
                else 
                    p = path + "/";
    
                if (!path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
                    copyFileOrDir(TARGET_BASE_PATH, p + assets[i]);
            }
        }
    } catch (IOException ex) {
        Log.e("tag", "I/O Exception", ex);
    }
    }
    
    private void copyFile(String TARGET_BASE_PATH, String filename) {
    AssetManager assetManager = this.getAssets();
    
    InputStream in = null;
    OutputStream out = null;
    String newFileName = null;
    try {
        Log.i("tag", "copyFile() "+filename);
        in = assetManager.open(filename);
        if (filename.endsWith(".jpg")) // extension was added to avoid compression on APK file
            newFileName = TARGET_BASE_PATH + "/" + filename.substring(0, filename.length()-4);
        else
            newFileName = TARGET_BASE_PATH + "/" + filename;
        out = new FileOutputStream(newFileName);
    
        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
    } catch (Exception e) {
        Log.e("tag", "Exception in copyFile() of "+newFileName);
        Log.e("tag", "Exception in copyFile() "+e.toString());
    }
    
    }


2

Bunu yapmanın iki yolu vardır.

İlk olarak, kullanabileceğiniz AssetManager.open tarif ettiği ve Rohith Nandakumar inputStream üzerinde ve yineleme.

İkinci olarak, kullanabilirsiniz AssetManager.openFd bir kullanma olanağı sunan, FileChannel sahiptir ([transferTo] ( https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferTo(long , uzun, java.nio.channels.WritableByteChannel)) ve [transferFrom] ( https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferFrom(java.nio.channels.ReadableByteChannel , uzun, long)) yöntemleri), bu nedenle giriş akışını kendiniz döngü yapmanıza gerek yoktur.

Burada openFd yöntemini açıklayacağım.

Sıkıştırma

Öncelikle dosyanın sıkıştırılmamış olarak saklandığından emin olmanız gerekir. Paketleme sistemi, noCompress olarak işaretlenmemiş bir uzantıya sahip herhangi bir dosyayı sıkıştırmayı seçebilir ve sıkıştırılmış dosyalar bellek eşlenemez, bu nedenle AssetManager.open dosyasına güvenmeniz gerekir. dosyasına .

Sıkıştırılmasını durdurmak için dosyanıza bir '.mp3' uzantısı ekleyebilirsiniz, ancak uygun çözüm app / build.gradle dosyanızı değiştirmek ve aşağıdaki satırları eklemektir (PDF dosyalarının sıkıştırılmasını devre dışı bırakmak için)

aaptOptions {
    noCompress 'pdf'
}

Dosya paketleme

Paketleyicinin birden fazla dosyayı tek bir pakete koyabildiğini unutmayın, böylece AssetManager'ın size verdiği dosyanın tamamını okuyamazsınız . AssetFileDescriptor'a sormanız gerekir hangi parçalara gerekir.

Paketlenmiş dosyanın doğru kısmını bulma

Eğer dosya sıkıştırılmamış saklanır emin olduktan sonra kullanabilirsiniz AssetManager.openFd bir elde etmek yöntemi AssetFileDescriptor bir elde etmek için kullanılabilir, FileInputStream (aksine AssetManager.open bir döndüren, InputStream bir içerir) FileChannel . Ayrıca , dosyanın doğru bölümünü elde etmek için gereken başlangıç ​​ofsetini (getStartOffset) ve boyutunu (getLength) içerir.

uygulama

Örnek bir uygulama aşağıda verilmiştir:

private void copyFileFromAssets(String in_filename, File out_file){
    Log.d("copyFileFromAssets", "Copying file '"+in_filename+"' to '"+out_file.toString()+"'");
    AssetManager assetManager = getApplicationContext().getAssets();
    FileChannel in_chan = null, out_chan = null;
    try {
        AssetFileDescriptor in_afd = assetManager.openFd(in_filename);
        FileInputStream in_stream = in_afd.createInputStream();
        in_chan = in_stream.getChannel();
        Log.d("copyFileFromAssets", "Asset space in file: start = "+in_afd.getStartOffset()+", length = "+in_afd.getLength());
        FileOutputStream out_stream = new FileOutputStream(out_file);
        out_chan = out_stream.getChannel();
        in_chan.transferTo(in_afd.getStartOffset(), in_afd.getLength(), out_chan);
    } catch (IOException ioe){
        Log.w("copyFileFromAssets", "Failed to copy file '"+in_filename+"' to external storage:"+ioe.toString());
    } finally {
        try {
            if (in_chan != null) {
                in_chan.close();
            }
            if (out_chan != null) {
                out_chan.close();
            }
        } catch (IOException ioe){}
    }
}

Bu cevap JPM'nin cevabına dayanmaktadır .


1
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        copyReadAssets();
    }


    private void copyReadAssets()
    {
        AssetManager assetManager = getAssets();

        InputStream in = null;
        OutputStream out = null;

        String strDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator + "Pdfs";
        File fileDir = new File(strDir);
        fileDir.mkdirs();   // crear la ruta si no existe
        File file = new File(fileDir, "example2.pdf");



        try
        {

            in = assetManager.open("example.pdf");  //leer el archivo de assets
            out = new BufferedOutputStream(new FileOutputStream(file)); //crear el archivo


            copyFile(in, out);
            in.close();
            in = null;
            out.flush();
            out.close();
            out = null;
        } catch (Exception e)
        {
            Log.e("tag", e.getMessage());
        }

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.parse("file://" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + File.separator + "Pdfs" + "/example2.pdf"), "application/pdf");
        startActivity(intent);
    }

    private void copyFile(InputStream in, OutputStream out) throws IOException
    {
        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1)
        {
            out.write(buffer, 0, read);
        }
    }
}

kod bölümlerini şu şekilde değiştirin:

out = new BufferedOutputStream(new FileOutputStream(file));

önceki örnek, .txt örneğinde Pdfs içindir

FileOutputStream fos = new FileOutputStream(file);

1

AssetManager'ı kullanın , varlıklardaki dosyaların okunmasına izin verir. Sonra dosyaları sdcard'a yazmak için normal Java IO'yu kullanın.

Google arkadaşınızdır, bir örnek arayın.


1

Merhaba arkadaşlar ben böyle bir şey yaptım. N-inci Derinlik Kopyalama Klasörü ve Dosyaları için. Ki Android AssetManager'dan kopyalamak için tüm dizin yapısını kopyalamanızı sağlar :)

    private void manageAssetFolderToSDcard()
    {

        try
        {
            String arg_assetDir = getApplicationContext().getPackageName();
            String arg_destinationDir = FRConstants.ANDROID_DATA + arg_assetDir;
            File FolderInCache = new File(arg_destinationDir);
            if (!FolderInCache.exists())
            {
                copyDirorfileFromAssetManager(arg_assetDir, arg_destinationDir);
            }
        } catch (IOException e1)
        {

            e1.printStackTrace();
        }

    }


    public String copyDirorfileFromAssetManager(String arg_assetDir, String arg_destinationDir) throws IOException
    {
        File sd_path = Environment.getExternalStorageDirectory(); 
        String dest_dir_path = sd_path + addLeadingSlash(arg_destinationDir);
        File dest_dir = new File(dest_dir_path);

        createDir(dest_dir);

        AssetManager asset_manager = getApplicationContext().getAssets();
        String[] files = asset_manager.list(arg_assetDir);

        for (int i = 0; i < files.length; i++)
        {

            String abs_asset_file_path = addTrailingSlash(arg_assetDir) + files[i];
            String sub_files[] = asset_manager.list(abs_asset_file_path);

            if (sub_files.length == 0)
            {
                // It is a file
                String dest_file_path = addTrailingSlash(dest_dir_path) + files[i];
                copyAssetFile(abs_asset_file_path, dest_file_path);
            } else
            {
                // It is a sub directory
                copyDirorfileFromAssetManager(abs_asset_file_path, addTrailingSlash(arg_destinationDir) + files[i]);
            }
        }

        return dest_dir_path;
    }


    public void copyAssetFile(String assetFilePath, String destinationFilePath) throws IOException
    {
        InputStream in = getApplicationContext().getAssets().open(assetFilePath);
        OutputStream out = new FileOutputStream(destinationFilePath);

        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0)
            out.write(buf, 0, len);
        in.close();
        out.close();
    }

    public String addTrailingSlash(String path)
    {
        if (path.charAt(path.length() - 1) != '/')
        {
            path += "/";
        }
        return path;
    }

    public String addLeadingSlash(String path)
    {
        if (path.charAt(0) != '/')
        {
            path = "/" + path;
        }
        return path;
    }

    public void createDir(File dir) throws IOException
    {
        if (dir.exists())
        {
            if (!dir.isDirectory())
            {
                throw new IOException("Can't create directory, a file is in the way");
            }
        } else
        {
            dir.mkdirs();
            if (!dir.isDirectory())
            {
                throw new IOException("Unable to create directory");
            }
        }
    }

Sonunda bir Asynctask oluşturun:

    private class ManageAssetFolders extends AsyncTask<Void, Void, Void>
    {

        @Override
        protected Void doInBackground(Void... arg0)
        {
            manageAssetFolderToSDcard();
            return null;
        }

    }

Faaliyetinizden:

    new ManageAssetFolders().execute();

1

Bir klasörü özyinelemeli olarak kopyalamak ve özel hedefi barındırmak için yukarıdaki cevabın hafifçe değiştirilmesi.

public void copyFileOrDir(String path, String destinationDir) {
    AssetManager assetManager = this.getAssets();
    String assets[] = null;
    try {
        assets = assetManager.list(path);
        if (assets.length == 0) {
            copyFile(path,destinationDir);
        } else {
            String fullPath = destinationDir + "/" + path;
            File dir = new File(fullPath);
            if (!dir.exists())
                dir.mkdir();
            for (int i = 0; i < assets.length; ++i) {
                copyFileOrDir(path + "/" + assets[i], destinationDir + path + "/" + assets[i]);
            }
        }
    } catch (IOException ex) {
        Log.e("tag", "I/O Exception", ex);
    }
}

private void copyFile(String filename, String destinationDir) {
    AssetManager assetManager = this.getAssets();
    String newFileName = destinationDir + "/" + filename;

    InputStream in = null;
    OutputStream out = null;
    try {
        in = assetManager.open(filename);
        out = new FileOutputStream(newFileName);

        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
    } catch (Exception e) {
        Log.e("tag", e.getMessage());
    }
    new File(newFileName).setExecutable(true, false);
}

1

Rohith Nandakumar'ın çözümüne dayanarak, varlıkların bir alt klasöründen dosyaları kopyalamak için kendime ait bir şey yaptım (örn. "Varlıklar / MyFolder "). Ayrıca, tekrar kopyalamaya çalışmadan önce dosyanın zaten sdcard içinde olup olmadığını kontrol ediyorum.

private void copyAssets() {
    AssetManager assetManager = getAssets();
    String[] files = null;
    try {
        files = assetManager.list("MyFolder");
    } catch (IOException e) {
        Log.e("tag", "Failed to get asset file list.", e);
    }
    if (files != null) for (String filename : files) {
        InputStream in = null;
        OutputStream out = null;
        try {
          in = assetManager.open("MyFolder/"+filename);
          File outFile = new File(getExternalFilesDir(null), filename);
          if (!(outFile.exists())) {// File does not exist...
                out = new FileOutputStream(outFile);
                copyFile(in, out);
          }
        } catch(IOException e) {
            Log.e("tag", "Failed to copy asset file: " + filename, e);
        }     
        finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    // NOOP
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    // NOOP
                }
            }
        }  
    }
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
    byte[] buffer = new byte[1024];
    int read;
    while((read = in.read(buffer)) != -1){
      out.write(buffer, 0, read);
    }
}

0

Bu, internette bulabildiğim en iyi çözüm. Aşağıdaki bağlantıyı kullandım https://gist.github.com/mhasby/026f02b33fcc4207b302a60645f6e217 ,
ancak düzelttiğim tek bir hata vardı ve sonra bir cazibe gibi çalışıyor. İşte kodum. Bağımsız bir java sınıfı olduğu için kolayca kullanabilirsiniz.

public class CopyAssets {
public static void copyAssets(Context context) {
    AssetManager assetManager = context.getAssets();
    String[] files = null;
    try {
        files = assetManager.list("");
    } catch (IOException e) {
        Log.e("tag", "Failed to get asset file list.", e);
    }
    if (files != null) for (String filename : files) {
        InputStream in = null;
        OutputStream out = null;
        try {
            in = assetManager.open(filename);

            out = new FileOutputStream(Environment.getExternalStorageDirectory()+"/www/resources/" + filename);
            copyFile(in, out);
        } catch(IOException e) {
            Log.e("tag", "Failed to copy asset file: " + filename, e);
        }
        finally {
            if (in != null) {
                try {
                    in.close();
                    in = null;
                } catch (IOException e) {

                }
            }
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                    out = null;
                } catch (IOException e) {

                }
            }
        }
    }
}

public static void copyFile(InputStream in, OutputStream out) throws IOException {
    byte[] buffer = new byte[1024];
    int read;
    while((read = in.read(buffer)) != -1){
        out.write(buffer, 0, read);
    }
}}

Gördüğünüz gibi CopyAssetsjava sınıfınızda bir etkinliği olan bir örneği oluşturun . Şimdi bu kısım, internette test ve araştırma yaptığım kadar önemli You cannot use AssetManager if the class has no activity. Java sınıfının içeriğiyle bir ilgisi var.
Şimdi, c.copyAssets(getApplicationContext())yönteme, sınıfın nerede cve örneğine erişmenin kolay bir yoludur CopyAssets. Gereksinimime göre, programın assetklasör içindeki tüm kaynak dosyalarımı /www/resources/dahili dizinimin içine kopyalamasına izin verdim.
Kullanımınıza göre dizinde değişiklik yapmanız gereken kısmı kolayca bulabilirsiniz. Yardıma ihtiyacınız olursa bana ping atmaktan çekinmeyin.


0

Kotlin'e güncelleme yapanlar için:

Bundan kaçınmak için bu adımları uygulayarak FileUriExposedExceptions, kullanıcıya WRITE_EXTERNAL_STORAGEizin verildiğini ve dosyanızın bulunduğunu varsayalım assets/pdfs/mypdf.pdf.

private fun openFile() {
    var inputStream: InputStream? = null
    var outputStream: OutputStream? = null
    try {
        val file = File("${activity.getExternalFilesDir(null)}/$PDF_FILE_NAME")
        if (!file.exists()) {
            inputStream = activity.assets.open("$PDF_ASSETS_PATH/$PDF_FILE_NAME")
            outputStream = FileOutputStream(file)
            copyFile(inputStream, outputStream)
        }

        val uri = FileProvider.getUriForFile(
            activity,
            "${BuildConfig.APPLICATION_ID}.provider.GenericFileProvider",
            file
        )
        val intent = Intent(Intent.ACTION_VIEW).apply {
            setDataAndType(uri, "application/pdf")
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
        }
        activity.startActivity(intent)
    } catch (ex: IOException) {
        ex.printStackTrace()
    } catch (ex: ActivityNotFoundException) {
        ex.printStackTrace()
    } finally {
        inputStream?.close()
        outputStream?.flush()
        outputStream?.close()
    }
}

@Throws(IOException::class)
private fun copyFile(input: InputStream, output: OutputStream) {
    val buffer = ByteArray(1024)
    var read: Int = input.read(buffer)
    while (read != -1) {
        output.write(buffer, 0, read)
        read = input.read(buffer)
    }
}

companion object {
    private const val PDF_ASSETS_PATH = "pdfs"
    private const val PDF_FILE_NAME = "mypdf.pdf"
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.