I am making an android webview application,there are a lot of files such as js/css/images must be downloaded from CDN to the app, because the network is not stable in our region and the size of the cached files is much bigger than the app itself, is there some way to build the apk file with the cache files stored automatically when the app runs at first few times.
Put your files and folders to assets. you'll find it in your project directory. When your application runs copy all assets contents to your SD card. then run your app :)
If you need any help about how to copy assets content to SD card let me know.
Copy Assets contents to SD card
Bellow code will copy all the contents of specified folder of your assets to your specified location of your SD card
CopyAssetContents.java
public class CopyAssetContents {
public static boolean copyAssetFolder(AssetManager assetManager,String fromAssetPath, String toPath) {
try {
String[] files = assetManager.list(fromAssetPath);
new File(toPath).mkdirs();
boolean res = true;
for (String file : files)
if (file.contains("."))
res &= copyAsset(assetManager,
fromAssetPath + "/" + file,
toPath + "/" + file);
else
res &= copyAssetFolder(assetManager,
fromAssetPath + "/" + file,
toPath + "/" + file);
return res;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean copyAsset(AssetManager assetManager,
String fromAssetPath, String toPath) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(fromAssetPath);
new File(toPath).createNewFile();
out = new FileOutputStream(toPath);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
return true;
} catch(Exception e) {
e.printStackTrace();
return false;
}
}
private 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);
}
}
}
For example you have all your contents in a folder named "CONTENTS" inside of your assets.and want to copy all of its content to root of your SD card.
call bellow method.
CopyAssetContents.copyAssetFolder(getAssets(), "CONTENTS", Environment.getExternalStorageDirectory().getAbsolutePath());
Related
I am making a soundboard for practice and I want to give the user the ability to download the sound (that I have included in the app in the res/raw folder) onClick of a menu item but I can only find information about downloading from an internet url, not something that I already included in the apk.
What is the best way to do this? I would like to give them the option to save to an SD card also if this is possible. A point towards the correct class to use in the documentation would be great! I've been googling to no avail.
Thanks!
Try something like this:
public void saveResourceToFile() {
InputStream in = null;
FileOutputStream fout = null;
try {
in = getResources().openRawResource(R.raw.test);
String downloadsDirectoryPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
String filename = "myfile.mp3"
fout = new FileOutputStream(new File(downloadsDirectoryPath + filename));
final byte data[] = new byte[1024];
int count;
while ((count = in.read(data, 0, 1024)) != -1) {
fout.write(data, 0, count);
}
} finally {
if (in != null) {
in.close();
}
if (fout != null) {
fout.close();
}
}
}
I don't know about the raw but I did a similar thing in my app using the assets folder. My files are under the assets/backgrounds folder as you can probably guess from the code below.
You can modify this code and make it work for you (I know I will only have 4 files which is why I have i go from 0 to 4 but you can change this to whatever you want).
This code copies the file starting with prefix_ (like prefix_1.png, prefix_2.png, etc) to my cache directory but you can obviously change the extension, the filename or the path you would like to save the assets to.
public static void copyAssets(final Context context, final String prefix) {
for (Integer i = 0; i < 4; i++) {
String filename = prefix + "_" + i.toString() + ".png";
File f = new File(context.getCacheDir() + "/" + filename);
if (f.exists()) {
f.delete();
}
if (!f.exists())
try {
InputStream is = context.getAssets().open("backgrounds/" + filename);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
FileOutputStream fos = new FileOutputStream(f);
fos.write(buffer);
fos.close();
} catch (Exception e) {
Log.e("Exception occurred while trying to load file from assets.", e.getMessage());
}
}
}
I'm writing app for android and I'm using caffe library. My problem is that on start I need to initialize caffe, which is done by passing two files (structures of network) to caffe.
Problem is that I don't know how to store extra files on device. I've added model file to assets, but I don't know how can I read it using file path. Can you tell me where to store these file that could be access using file path?
Thanks for any ideas.
This should do it. Just copy those files to data directory from asset folder. If you already have those files there just load them.
String toPath = "/data/data/" + getPackageName(); // Your application path
private static boolean copyAssetFolder(AssetManager assetManager,
String fromAssetPath, String toPath) {
try {
String[] files = assetManager.list(fromAssetPath);
new File(toPath).mkdirs();
boolean res = true;
for (String file : files)
if (file.contains("."))
res &= copyAsset(assetManager,
fromAssetPath + "/" + file,
toPath + "/" + file);
else
res &= copyAssetFolder(assetManager,
fromAssetPath + "/" + file,
toPath + "/" + file);
return res;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean copyAsset(AssetManager assetManager,
String fromAssetPath, String toPath) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(fromAssetPath);
new File(toPath).createNewFile();
out = new FileOutputStream(toPath);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
return true;
} catch(Exception e) {
e.printStackTrace();
return false;
}
}
private 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);
}
}
Put them into your project as assets, and then when the app starts, you can read them from the assets and copy them into the app's private storage area. You can find this directory using Context.getFilesDir().
From there, you'll be able to pass the files to Caffe.
Assets are packaged and access only using special methods, so i solved problem by access file and then copy it to new location which i passed to native method.
i am making a quiz app and i have stored images in assets folder say assets/pictures.I retrieve images from assets folder using AssetsManager.But after i add few more images to assets folder i found that the application do not fetch updated image from assets folder unless i uninstall the previous app.I also learned that its isn't possible to update assets folder unless i uninstall old app.Am i correct? I would like to know if its possible to added assets folder images to a database and use database to retrieve images to app?Also will my new image files will be shown when i release an updated version of my app?If so how?
This is what i use to rad from assets folder
String[] getImagesFromAssets() {
AssetManager assetManager = getAssets();
String[] img_files = null;
try {
// img_files = getAssets().list("pictures");
img_files = assetManager.list("pictures");
} catch (IOException ex) {
Logger.getLogger(GameActivity.class
.getName()).log(Level.SEVERE, null, ex);
}
return img_files;
}
void loadImage(String name) {
AssetManager assetManager = getAssets();
System.out.println("File name => "+name);
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open("pictures/"+name); // if files resides inside the "Files" directory itself
out = new FileOutputStream(Environment.getExternalStorageDirectory() +"/" +"pictures/"+ name);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
Drawable d=Drawable.createFromPath(Environment.getExternalStorageDirectory() +"/" +"pictures/" + name);
image.setImageDrawable(d);
//Drawable d = Drawable.createFromStream(in, null);
//image.setImageDrawable(d);
} catch(Exception e) {
Log.e("tag", e.getMessage());
}
}
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);
}
}
The Assets folder is a build-time resource that is read-only for the Application. Once the files are specified in the APK, they cannot be changed at run time. You will need to use local storage to work with new files that your application creates.
I have a html file in my asset directory and i have to load it as browser application using Intent.
Here is my code, but its not working:
startActivity (new Intent(Intent.ACTION_VIEW,
Uri.parse("file:///android_asset/Sample.htm")));
Could anyone help me?
Use loadUrl() method of WebView to load an html page
Sample Example
if faq.html is the html file present in assets folder then you can use
WebView html = (WebView) findViewById(R.id.webEulaView);
html.loadUrl("file:///android_asset/faq.html");
i had the same problem what i did was
copied the content of the assets to a database and then pulled it from the sdcard
here is the code to copy your assets to sdcard
the logic used is as follows the html pages are put in the zip file in assets folder
content is the name of the zip in assets folder
boolean succussFlag = false;
destination="";
destination=Environment.getExternalStorageDirectory()+"/";
File file = new File(destination);
if (!file.exists()){
file.mkdirs();
}
else
{
//file.delete();
//file.mkdir();
}
try
{
InputStream fileInput = context.getAssets().open("content.zip");
ZipInputStream inputStream = new ZipInputStream(fileInput);
for (ZipEntry entry = inputStream.getNextEntry(); entry != null; entry = inputStream.getNextEntry())
{
String innerFileName = destination + entry.getName();
System.out.println("destination::::"+innerFileName);
// Log.v("inner file name 0",""+innerFileName);
File innerFile = new File(innerFileName);
if (innerFile.exists())
{
innerFile.delete();
}
// Check if it is a folder
if (entry.isDirectory())
{
// Its a folder, create that folder
innerFile.mkdirs();
}
else
{
// System.out.println(" ::::::::::::::INNER FILE COPYING :::: " + innerFile.toString());
FileOutputStream outputStream = new FileOutputStream(innerFileName);
final int BUFFER = 4096;
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream,
BUFFER);
int count = 0;
byte[] data = new byte[BUFFER];
while ((count = inputStream.read(data, 0, BUFFER)) != -1)
{
bufferedOutputStream.write(data, 0, count);
}
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
inputStream.closeEntry();
}
inputStream.close();
// System.out.println(" ::::::::::COPIED TO PRIVATE FOLDER :::: " );
succussFlag=true;
}
catch (IOException e)
{
// System.out.println("** EXCEPTION OCCURED WHILE COPYING***");
e.printStackTrace();
succussFlag=false;
}
return succussFlag;
after this you give following command
startActivity (new Intent(Intent.ACTION_VIEW,"file://"+ Environment.getExternalStorageDirectory()+"/content"+name_Html ;
);
I am trying to create a folder and several subdirectory within it on the SD Card... I then want to transfer files that I have stored in /res/raw to that folder... I addition, I want this to only happen once, the first time the program is ever run. I realize that this is ridiculously open-ended, and that I am asking a lot... but any help would be greatly appreciated.
This will copy all files in the "clipart" subfolder of the .apk assets folder to the "clipart" subfolder of your app's folder on the SD card:
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
String basepath = extStorageDirectory + "/name of your app folder on the SD card";
//...
// in onCreate
File clipartdir = new File(basepath + "/clipart/");
if (!clipartdir.exists()) {
clipartdir.mkdirs();
copyClipart();
}
private void copyClipart() {
AssetManager assetManager = getResources().getAssets();
String[] files = null;
try {
files = assetManager.list("clipart");
} catch (Exception e) {
Log.e("read clipart ERROR", e.toString());
e.printStackTrace();
}
for(int i=0; i<files.length; i++) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open("clipart/" + files[i]);
out = new FileOutputStream(basepath + "/clipart/" + files[i]);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch(Exception e) {
Log.e("copy clipart ERROR", e.toString());
e.printStackTrace();
}
}
}
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);
}
}
I experienced a similar problem when using mkdirs(), however because running the command:
mkdir one/two
fails on Linux, then the method http://download.oracle.com/javase/1.4.2/docs/api/java/io/File.html#mkdirs() subsequently fails too. I guess this means there is no way to use mkdirs on Android? My (probably rather hacky) work-around was to create each necessary directory separately:
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
new File(extStorageDirectory + "/one/").mkdirs();
new File(extStorageDirectory + "/one/two/).mkdirs();