i have a subfolder in the Assets folder called images where i store my images(of course) :) The things is that i want to get the name for the images which i'm getting but the problem is that i'm also getting other unknown names like: "android-logo-mask.png" which i guess are android's default images. Is there a way i can skip this "android default images" to get only the names of my images? My plan is to save this names in a database to use it as reference for showing the images later on an ImageView. Is it a good idea to use the image name to show the images? Here is some code if it needs:
Context context;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context = this.getApplicationContext();
ImageHelper i = new ImageHelper();
i.readImages(context);
}
public class ImageHelper {
public ImageHelper(){}
public void readImages(Context context){
AssetManager am = context.getAssets();
try {
String[] getImages = am.list("images");
for(String imgName : getImages){
Log.e("IMAGE NAME----->", imgName);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks in advance.
Use some other name for images folder like "MyImages". It should work fine then.
"images" should be a path like "/path/assets/images/image.png"
It is very interesting. Even if you don't have an assets/images directory, when you use:
myImageList = Arrays.asList(getResources().getAssets().list("images"));
you'll see android-logo-mask.png and android-logo-shine.png listed in the results.
That led me to wondering where those actual image files live in the Android code. I don't know the code base at all, but:
https://android.googlesource.com/platform/frameworks/base/+/master/core/res/assets/images/
lists those two in an assets directory under res. (Different from the assets directory where I store my project assets, that's not under res).
Being required to provide a path to an individual file for the AssetManagers list method (which returns an array) just doesn't make any sense. And the method documentation says:
Return a String array of all the assets at the given path.
It makes me wonder if there's an error in the list method, or if there was some other reason it was designed to return particular system assets when an asset list is required.
In a similar fashion, if I use:
myAssetList = Arrays.asList(getResources().getAssets().list(""));
I see "sounds" and "webkit" included, which don't correspond to any existing subdirectory of my assets.
If it occurs that the system adds files in this "images" folder, why not create a new folder for your images that you are sure to contain only your files ?
Related
i am trying to get this really easy setup to work, and it works on my computer but not on Android.
After trying it for the whole day im now asking since i cant find a single example on the internet.
The setup:
I have a lot of *.png files in a folder. Since the problem is with android i put them into a "StreamingAssets" folder
I have a RawImage called "Overlay"
I have a Dropdown called "Dropdown"
What should happen:
1. The Dropdown_script checks the StreamingAssets folder for all *.png files and adds every Filename to the dropdown options menu.
2. Once the user chooses one of the dropdown values my "Overlay" image changes its texture to the according file.
Pretty easy on PC ... impossible on android(with unity3d) as it seems.
My Dropdown Script:
public class DDScript : MonoBehaviour {
void Start () {
GameObject obj = GameObject.Find("Dropdown");
//Get all filenames
var info = new DirectoryInfo(Application.streamingAssetsPath);
var fileInfo = info.GetFiles("*.png");
//Clear the DropDown Menu Items from the Inspector
obj.GetComponent<Dropdown>().options.Clear();
//Make the first chosen item the first filename
obj.GetComponent<Dropdown>().captionText.text = fileInfo[0].Name.Substring(0, fileInfo[0].Name.IndexOf("."));
foreach (var file in fileInfo)
{
Dropdown.OptionData list = new Dropdown.OptionData(file.Name.Substring(0, file.Name.IndexOf(".")));
obj.GetComponent<Dropdown>().options.Add(list);
}
}
Its not working. It is working on my Computer but it is just not working on Android. I know that under Android everything gets packed into a jar file and there is nothing like a folderstructure. StreamingAssets should still have the files but i can understand that this part maybe cant work. Which would not be that bad, since it just finds the names and puts it into an array, i could do that within the program by hand. Since i know from beforehand how much and which files will be in the folder and it wont change ever.
This is my Change Texture Method
It is invoked by the Dropdown OnValueChange so the "newOverlay" is simply the int from the Dropdown. For debugging purposes i set the filepath to a specific file. later it will change depending on newOverlay
public IENumerator SetOverlay(int newOverlay)
{
GameObject obj = GameObject.Find("Overlay");
img = (RawImage)obj.GetComponent<RawImage>();
string filePath = System.IO.Path.Combine(Application.streamingAssetsPath, "testfile.png");
WWW www = new WWW(filePath);
yield return www;
img.texture = www.texture;
}
And i do not understand why this is not working!
The Documentation reads:
" This means that if you do not use Unity’s WWW class to retrieve the file then you will need to use additional software"
So using www is the right way. But it is not working!
No Texture gets loaded. i dont get the red questionmark, my image is just plain white. Please can someone help me here? Maybe i just cant see the forest due to all of the trees or the day was too long.
I really just cant believe that it is this hard to load a bunch of images that are within my apk file wiht unity :(
Thank you very much in advance
Edit: Solution (somehow)
First of all the problem was that System.IO.Path.Combine adds a back-slash between file and folder, but not between the folders themself!!!!
public void SetOverlay(int newOverlay)
{
GameObject obj = GameObject.Find("Overlay");
img = (RawImage)obj.GetComponent<RawImage>();
string filePath = Application.streamingAssetsPath + "/testfile.png";
WWW www = new WWW(filePath);
while (!www.isDone)
{}
img.texture = www.texture;
GameObject.Find("DebugText").GetComponent<Text>().text = filePath;
}
Havent found a solution to the Filename problem yet but im glad that this stupid "bug" is resolved
Have you tried putting the png files into the drawable folder and accessing them with BitmapFactory.decodeResources()?
I am developing an android game app and I have more then 150 images inside my app!
I want to put all images which exist in drawable package in a ArrayList.
I have this code
InputStream ips = getAssets().open("Arrow001.jpg");
Drawable d = Drawable.createFromStream(ips, null);
questionImageView.setImageDrawable(d);
but i don't want to add them one by one in myArray and i want to use a loop for generate images in arrayList when i run my app!
Thanks for your help
You can get array of all assets files on root assets folder by calling
String[] list = getAssets().list("")
In our case you can write code like below.
for (String assetPath : getAssets().list("")) {
InputStream ips = getAssets().open(assetPath);
//yours code
}
I'm trying to populate a ListView with a mixture of files stored on the SDcard AND stored as assets in the APK. Using TraceView, I can see that the performance of AssetManager.list() is poor in comparison to File.listFiles(), even though I'm using a filename filter for the SDcard.
Here is a simple method that returns all the png files from a folder on the SDcard:
// The folder on SDcard may contain files other than png, so filter them out
private File[] getMatchingFiles(File path) {
File[] flFiles = path.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
name = name.toLowerCase();
return name.endsWith(".png");
}
});
return flFiles;
}
I invoke that method here and it takes about 12ms to retrieve 16 files:
final String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)||Environment.MEDIA_SHARED.equals(state)) {
File path = Environment.getExternalStoragePublicDirectory(getResources().getString(R.string.path_dir));
if (path.exists()){
File[] files = getMatchingFiles(path);
...
Whereas the am.list method takes 49ms to retrieve just the names of about 6 files!
// Get all filenames from specific Asset Folder and store them in String array
AssetManager am = getAssets();
String path = getResources().getString(R.string.path_dir);
String[] fileNames = am.list(path);
...
Can anyone explain why the performance would be so poor? Is the performance proportional to the number of assets stored in the APK? I'm aware that assets are compressed, but I'm only fetching the names of the assets, which I thought would be stored in a table somewhere.
Coverdriven's comment "stored in a table somewhere" inspired me to solve my own problem which I've been putting off for a while.
This doesn't answer the OP but does offer a different approach and it handles subfolders which CommonsWare's solution doesn't unless you go recursive (which of course is another possible solution). It's specifically aimed at apps which have a large number of assets in subfolders.
I added an ANT pre-build target to run this command (I'm on Windows)
dir assets /b /s /A-d > res\raw\assetfiles
This creates a recursive (/s), barebones (/b) listing of all files, excluding directory entries (/A-d) in my assets folder.
I then created this class to statically load the contents of assetfiles into a hashmap, the key of which is the filename and the value the full path
public class AssetFiles {
// create a hashmap of all files referenced in res/raw/assetfiles
/*map of all the contents of assets located in the subfolder with the name specified in FILES_ROOT
the key is the filename without path, the value is the full path relative to FILES_ROOT
includes the root, e.g. harmonics_data/subfolder/file.extension - this can be passed
directly to AssetManager.open()*/
public static HashMap<String, String> assetFiles = new HashMap<String, String>();
public static final String FILES_ROOT = "harmonics_data";
static {
String line;
String filename;
String path;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(TidesPlannerApplication.getContext().getResources().openRawResource(R.raw.assetfiles)));
while ((line = reader.readLine()) != null) {
// NB backlash (note the escape) is specific to Windows
filename = line.substring(line.lastIndexOf("\\")+1);
path = line.substring(line.lastIndexOf(FILES_ROOT)).replaceAll("\\\\","/");;
assetFiles.put(filename, path);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static boolean exists(String filename){
return assetFiles.containsKey(filename);
}
public static String getFilename(String filename){
if (exists(filename)){
return assetFiles.get(filename);
} else {
return "";
}
}
}
To use it, I simply call AssetFiles.getFilename(filename) which returns the full path which I can pass to AssetManager.open(). Much much faster!
NB. I haven't finished this class and it's not hardened yet so you'll need to add appropriate exception catches and actions. It's also quite specific to my app in that all of my assets are in subfolders which are in turn located in a subfolder of the assets folder (see FILES_ROOT) but easy to adapt to your situation.
Note also the need to replace backslashes, since Windows generates the assetfiles listing, with forward slashes. You could eliminate this on OSX and *nix platforms.
Can anyone explain why the performance would be so poor?
Reading the contents of a ZIP archive (the APK where the assets are located) is slower than reading the contents of a directory on the filesystem, apparently. In the abstract, this is not especially surprising, as I suspect that this would be true for all major operating systems.
Read in that list() data once, then save it somewhere else for faster access (e.g., database), particularly in a form that is optimized for future lookups (e.g., where a simple database query could give you what you want, vs. having to load and "recursively search it" again).
If you have a deep tree of directories in the assets you can detect firstly if an item is file or directory and then call .list() on it (really accelerates the walking through the tree). This is my solution I've discovered for this:
try {
AssetFileDescriptor desc = getAssets().openFd(path); // Always throws exception: for directories and for files
desc.close(); // Never executes
} catch (Exception e) {
exception_message = e.toString();
}
if (exception_message.endsWith(path)) { // Exception for directory and for file has different message
// Directory
} else {
// File
}
You can approach APK package as it's a ZIP file and read all the entries using Java's builtin ZipFile. It will give you all the file names with their full paths. Perhaps it shouldn't be hard to find which directories you have.
So far this is the fastest approach I've tested.
credit goes to #obastemur's commit on jxcore-android-basics sample project
I'm attempting to create a gallery/gridview that is loaded with images from a specific folder that resides on an SDCard. The path to the folder is known, ("mnt/sdcard/iWallet/Images") , but in the examples I've seen online I am unsure how or where to specify the path to the pictures folder I want to load images from. I have read through dozens of tutorials, even the HelloGridView tutorial at developer.android.com but those tutorials do not teach me what i am seeking.
Every tutorial I have read so far has either:
A) called the images as a Drawable from the /res folder and put them into an array to be loaded, not using the SDCard at all.
B) Accessed all pictures on the SDCard using the MediaStore but not specifying how to set the path to the folder I want to display images form
or
C) Suggested using BitmapFactory, which I haven't the slightest clue how to use.
If I'm going about this in the wrong way, please let me know and direct me toward the proper method to do what I'm trying to do.
my target android sdk version 1.6...
thanks..
You can directly create Bitmaps from decodeFile (String pathName) that will give you Bitmap object that can be set on ImageView
Update: Below is sudo code with minor errors modify it to suit your needs
File path = new File(Environment.getExternalStorageDirectory(),"iWallet/Images");
if(path.exists())
{
String[] fileNames = path.list();
}
for(int i = 0; i < fileNames .length; i++)
{
Bitmap mBitmap = BitmapFactory.decodeFile(path.getPath()+"/"+ fileNames[i]);
///Now set this bitmap on imageview
}
Actually, you are wrong to mention fixed path to access SD-card directory, because in some device it is /mnt/sdcard and in other /sdcard.
so to access root directory of sd-card, use the getExternalStorageDirectory(), it gives you actual path of root directory.
This function will resturn all the files from specific folder you need to pass path till ur folder
public static List getFilesFromDir(File aStartingDir)
{
List result = new ArrayList();
File[] filesAndDirs = aStartingDir.listFiles();
List filesDirs = Arrays.asList(filesAndDirs);
Iterator filesIter = filesDirs.iterator();
File file = null;
while ( filesIter.hasNext() ) {
file = (File)filesIter.next();
result.add(file); //always add, even if directory
if (!file.isFile()) {
//must be a directory
//recursive call!
List deeperList = getFileListing(file);
result.addAll(deeperList);
}
}
Collections.sort(result);
return result;
}
BitmapDrawable d = new BitmapDrawable(getResources(), path+".jpg"); // path is ur resultant //image
img.setImageDrawable(d);
Hope it help u...
You can access your directory using File java class, then iterate through all the files in there, create a bitmap for each file using Bitmapfactory.decodeFile() then add the bitmaps to your gallery.
I am newbie to android don't know much about it. I have imported a image to my project and when i tried it check it using File that the file exists or not.
This is the code i have used..
existingFileName="res/drawable-ldpi/login.png";
File f= new File(existingFileName);
// Log.d("Image path",);
if(f.exists())
{
Log.d("EXISTS", "====File Exists===");
}
Still it is showing me no image exist.
thanks for help in advance,
aby
If you are putting your images in drawable folder, I don't think you can access them like this. Try this
Drawable image= getResources().getDrawable(R.drawable.<id>);
id will be your file name.
If you store the image in the "res/drawable" folder you can do:
Drawable drawable = getResources().getDrawable(R.drawable.name)
See http://developer.android.com/reference/android/content/res/Resources.html#getDrawable
For the case you store your image in the assets folder, you need to use getAssets() ( http://developer.android.com/reference/android/content/Context.html#getAssets() )
You can do something like this:
InputStream is = getAssets().open(imageName);
BufferedInputStream buf = new BufferedInputStream(is);
Bitmap bitmap = BitmapFactory.decodeStream(buf);
Remember that for both case you need to have a Context (ie an Activity)
There is no need to check the existence of an asset file before you read it. AssetManager takes care of it. If file is missing, it throws an exception. Your coding practice should be to always enclose that part of code in try catch and split the logic. Extra code is not needed. If you try an open a file that doesn't exist you will get an exception.
Though, if you still want to do that manual job, try below code.
AssetManager mg = getResources().getAssets();
try {
//do all considering file exists
mg.open(pathInAssets);
} catch (IOException ex) {
//do all in case file is missing
}
If your file is located in assets/folder/file.ext, then pathInAssets would be "folder/file.ext"
Check for file existence in androids assets folder?
How to check Android Asset resource?
Usually if you use res/drawable, your ressource identifier is compiled into the R.java file. So if you use an identifier from there, you can be sure the file IS there, otherwise you cannot compile your project.
If however you like to exchange R.java later and really need to list the ressources in res/drawable, you can do it with java Reflection, examining the R class like this:
Class<?> c=R.drawable.class;
Field[] fs=c.getFields();
for(Field f: fs)
Log.v("test", f.getName());
You will then get a list of the ressources, without the file extension. The Ressource Identifier (an integer) for every ressource is then read with int id=f.getInt(null);.
Use the DDMS perspective in eclipse to browse for the image on an emulator running your app.
If you get this error.. "Cannot make a static reference to the non-static method getResources() from the type ContextWrapper"
Try Drawable image=Classname.this.getResources().getDrawable(R.drawable.<id>);
here Classname.this means the ClassContext/Application Context.