android get list of files from package - android

How can I get all list of .json config files, which are located NOT on SD card, but in my package? Bellow on the image showed the files in the folder which I want to access. The idea is the following: when application starts I want to get list of config files, the path to them and display that to testers to choose to what server connect to. How can I do that? I was looking for PackageManager and AssetManager, but resultless.
When I put folder configs to folder assets, this code game me a list of available configs, but how can I get full path to them to read them?
AssetManager am = getAssets();
String s = getPackageName();
Resources tmp = pm.getResourcesForApplication(s);
String [] arr = am.list("configs2");

To do a similar thing I've used the following command:
InputStream is = context.getResources().openRawResource(R.raw.raw_data_file);
Where the file raw_data_file was in the path res/raw/raw_data_file.txt. You can then read the file using the InputStream as normal. I'm sure you'd be able to do a similar thing with your file where it is, but as a rule I'd normally put any resources in the res(ources) folder

I finally solved my problem. This is the structure of my project:
To get list of files from application package, you need to put all your files you want to get into assets folder. Here is the code:
private ArrayList getPackageConfigList()
{
AssetManager am = getAssets();
String [] arr = null;
try
{
arr = am.list(folder);
}
catch(IOException e) {e.printStackTrace();}
ArrayList<String> flist = new ArrayList<String>();
for (int i=0; i<arr.length; i++)
{
flist.add(PKG + arr[i]);
Log.d(tag, PKG+ arr[i]);
}
return flist;
}
To read concrete file from package:
private String loadConfigFromPackage(String fileName)
{
AssetManager am = getAssets();
InputStream in = null;
String result = null;
try
{
//open file, read to buffer, convert to string
in = am.open(folder + "/" + fileName);
int size = in.available();
byte[] buffer = new byte[size];
in.read(buffer);
in.close();
result = new String(buffer);
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
in.close();
}
catch(Exception ex){}
}
return result;
}

Related

Storing file on Android for Native reading

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.

How to transfer a txt data file to my Android app

I must transfer a data file necessary for my app.
I read many threads on the subject and I stll don't understand how it works.
1. I'm using android studio 0.8.6. A lot of threads mentions the folder assets which apparently resides in src/main. When I create a new project the folder doesn't exist. I create manually one and I put in it jpg and txt files.
2. I run the following code:
AssetManager am = getAssets();
String[] files = new String[0];
try {
files = am.list("Files ;
} catch (IOException e) {
e.printStackTrace();
}
for(int i=0;i<files.length;i++){
Toast.makeText(getApplicationContext(), "File: "+files[i]+" ", Toast.LENGTH_SHORT).show();
}
And I get a files.length = 0
1. I can create files, write in it and read it but I don know where they reside.
And that's not what I want to do. I want to pass the data with the app.
Sorry for the long email but I'm lost.
Thanks in advance!
The code I have used to read files from assets is listed below:
public String ReadFromfile(String fileName, Context context) {
StringBuilder returnString = new StringBuilder();
InputStream fIn = null;
InputStreamReader isr = null;
BufferedReader input = null;
try {
fIn = context.getResources().getAssets()
.open(fileName, Context.MODE_WORLD_READABLE);
isr = new InputStreamReader(fIn);
input = new BufferedReader(isr);
String line = "";
while ((line = input.readLine()) != null) {
returnString.append(line);
}
} catch (Exception e) {
e.getMessage();
} finally {
try {
if (isr != null)
isr.close();
if (fIn != null)
fIn.close();
if (input != null)
input.close();
} catch (Exception e2) {
e2.getMessage();
}
}
return returnString.toString();
}
This code is not mine and can be found in the answers below:
read file from assets
I did some progress using the following code:
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
File dir = getFilesDir();
File f = new File("/data/data/com.example.bernard.myapp/");
File file[] = f.listFiles();
for(int i=0;i<file.length;i++){
Toast.makeText(getApplicationContext(), "File: "+String.valueOf(file[i]), Toast.LENGTH_SHORT).show();
}
}
I code in hard what seems to me like the root of my app:
File f = new File("/data/data/com.example.bernard.myapp/");
The result is I can see 3 files: lib, cache, files
in "files" appears the files I create running the app.
I still don't know where is assets, neither where I transfer/put the .txt and .jpg files I want to use with my app. I develop using studio.

Solution for updating Assets folder

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.

Font in Android Library

At the follow link
Android Dev Guide
is write:
Library projects cannot include raw assets
The tools do not support the use of raw asset files (saved in the assets/ directory) in a library project. Any asset resources used by an application must be stored in the assets/ directory of the application project itself. However, resource files saved in the res/ directory are supported.
So if I want to create a custom view component that use a custom font how can I access the resource? Can't I redistribute my component with my favorite font !!!!
Best regards
Here's a method for loading fonts from resources that actually works ;-)
Credit to mr32bit for the first version.
private Typeface getFontFromRes(int resource)
{
Typeface tf = null;
InputStream is = null;
try {
is = getResources().openRawResource(resource);
}
catch(NotFoundException e) {
Log.e(TAG, "Could not find font in resources!");
}
String outPath = getCacheDir() + "/tmp" + System.currentTimeMillis() ".raw";
try
{
byte[] buffer = new byte[is.available()];
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath));
int l = 0;
while((l = is.read(buffer)) > 0)
bos.write(buffer, 0, l);
bos.close();
tf = Typeface.createFromFile(outPath);
// clean up
new File(outPath).delete();
}
catch (IOException e)
{
Log.e(TAG, "Error reading in font!");
return null;
}
Log.d(TAG, "Successfully loaded font.");
return tf;
}
Ok I have found a workaround for the problem. You need to copy the file to an external directory then load a typeface from file with Typeface.createFromFile and then delete the temporary file. I know is not a clean mode of work but is working grate.
1 - You need to put your font on "/res/raw/font.ttf"
2 - Inser in your code the following method
3 - put in your code Typeface mFont = FileStreamTypeface(R.raw.font);
4 - All is done
Typeface FileStreamTypeface(int resource)
{
Typeface tf = null;
InputStream is = getResources().openRawResource(resource);
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/gmg_underground_tmp";
File f = new File(path);
if (!f.exists())
{
if (!f.mkdirs())
return null;
}
String outPath = path + "/tmp.raw";
try
{
byte[] buffer = new byte[is.available()];
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath));
int l = 0;
while((l = is.read(buffer)) > 0)
{
bos.write(buffer, 0, l);
}
bos.close();
tf = Typeface.createFromFile(outPath);
File f2 = new File(outPath);
f2.delete();
}
catch (IOException e)
{
return null;
}
return tf;
}
if someone have an alternative I'm pleased to read it.
Do you have to remember that this workaround is only for Android Libraries
Best regards
Intellij Idea (and android studio as it's based on intellij) has a feature that let you include the asset files of the library module to application module, I don't know about other environment.
Go to project structure in file menu, then facets, choose application module, in compiler tab check "include assets from dependencies to the into APK" checkbox.
As intellij is far better than Eclipse, I think migrating is reasonable.
EDIT:
Asset and manifest merging are fully supported in android studio.
If you extend a TextView and want to use many of this views you should have only one instance of the Typeface in this view. Copy the *.ttf file into res/raw/ and use the following code:
public class MyTextView extends TextView {
public static final String FONT = "font.ttf";
private static Typeface mFont;
private static Typeface getTypefaceFromFile(Context context) {
if(mFont == null) {
File font = new File(context.getFilesDir(), FONT);
if (!font.exists()) {
copyFontToInternalStorage(context, font);
}
mFont = Typeface.createFromFile(font);
}
return mFont;
}
private static void copyFontToInternalStorage(Context context, File font) {
try {
InputStream is = context.getResources().openRawResource(R.raw.font);
byte[] buffer = new byte[4096];
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(font));
int readByte;
while ((readByte = is.read(buffer)) > 0) {
bos.write(buffer, 0, readByte);
}
bos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setTypeface(getTypefaceFromFile(context));
}
}
mFont is a static variable, so the reference will not be destroyed and can be reused in other MyTextViews.
This code is nearly the same as the other answers but I guess mor efficient and consumes less memory if you are using it in a ListView or something.
So if I want to create a custom view component that use a custom font how can I access the resource?
Your code would access it the same way that it does not. You will simply have to tell reusers of your custom view to include the font file in their assets.
Can't I redistribute my component with my favorite font !!!!
Sure you can. Put the font in a ZIP file along with the rest of your library project, along with instructions for where to place it in a project. Be sure to use a font that you have rights to redistribute this way, though.
Even though You put Your fonts in assets/fonts folder, somehow this library works and its very easy to use: https://github.com/neopixl/PixlUI . I've successfully tested it on Android 2.3.
as well as 4.4
Just use the response of #bk138 with this little change it works to me
add this in the manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
and add this before creating the Buffered
File f2 = new File(outPath);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath));
The code below modifies the solution from #bk138 and includes #Jason Robinson recommendations for not deleting the file and checking for a previously cached file first. Also, it names the temp file after the font instead of the time created.
public static Typeface getFontFromRes(Context context, int resId, boolean deleteAfterwards){
String tag = "StorageUtils.getFontFromRes";
String resEntryName = context.getResources().getResourceEntryName(resId);
String outPath = context.getCacheDir() + "/tmp_" + resEntryName + ".raw";
//First see if the file already exists in the cachDir
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(outPath));
} catch (FileNotFoundException e) {
Log.d(tag,"fileNotFoundException outPath:"+outPath+e.getMessage());
}
if(fis != null){
try {
Log.d(tag,"found cached fontName:"+resEntryName);
fis.close();
} catch (IOException e) {
Log.d(tag,"IOException outPath:"+outPath+e.getMessage());
}
//File is already cached so return it now
return Typeface.createFromFile(outPath);
}
InputStream is = null;
try {
is = context.getResources().openRawResource(resId);
}catch(NotFoundException e) {
Log.e(tag, "Could not find font in resources! " + outPath);
}
try{
byte[] buffer = new byte[is.available()];
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath));
int l = 0;
while((l = is.read(buffer)) > 0)
bos.write(buffer, 0, l);
bos.close();
}catch (IOException e){
Log.e(tag, "Error reading in font!");
return null;
}
Typeface tf = Typeface.createFromFile(outPath);
if(deleteAfterwards){
// clean up if desired
new File(outPath).delete();
}
Log.d(tag, "Successfully loaded font.");
return tf;
}
Here's my modified version/improvement on #Mr32Bit's answer. On the first call, I copy the font to the app private dir /custom_fonts. Future reads check if exists and if so reads existing copy (saves time on coping file each time).
note: This assumes only a single custom font.
/**
* Helper method to load (and cache font in app private folder) typeface from raw dir this is needed because /assets from library projects are not merged in Eclipse
* #param c
* #param resource ID of the font.ttf in /raw
* #return
*/
public static Typeface loadTypefaceFromRaw(Context c, int resource)
{
Typeface tf = null;
InputStream is = c.getResources().openRawResource(resource);
String path = c.getFilesDir() + "/custom_fonts";
File f = new File(path);
if (!f.exists())
{
if (!f.mkdirs())
return null;
}
String outPath = path + "/myfont.ttf";
File fontFile = new File(outPath);
if (fontFile.exists()) {
tf = Typeface.createFromFile(fontFile);
}else{
try
{
byte[] buffer = new byte[is.available()];
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath));
int l = 0;
while((l = is.read(buffer)) > 0)
{
bos.write(buffer, 0, l);
}
bos.close();
tf = Typeface.createFromFile(outPath);
}
catch (IOException e)
{
return null;
}
}
return tf;
}

Android: How to create a directory on the SD Card and copy files from /res/raw to it?

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();

Categories

Resources