This is so stupid, I am certain I will be stabbing myself with a wet kipper in a few minutes..
I have this method, the purpose of which is to determine if a particular path in the assets folder is a subfolder. It's used in a recursive search to find files in assets.
private static boolean isDirectory(AssetManager assetManager, String path) throws IOException
{
// AssetManager.list() returns a string array of assets located @ path
// if path is a file, then the array will be empty and have zero length
// if path does not exist, then an IOException is raised
// (ignore the exception as in theory, this will never happen
// since this is called by the searchAssets recursive find)
// do nothing for uninitialised or empty paths
if (path==null || path.equals("")){return false;}
try {
if (DEBUG){Log.d(TApp.APP_TAG,path + " lists " + assetManager.list(path).length + " assets");}
if (assetManager.list(path).length > 0){
return true;
}
} catch (IOException e) {
// do nothing - path should always exist but in any case, there is nothing we can
// do so just throw it back up
throw e;
}
return false;
}
The problem is that it is always returning false.
When I step through the code, I can see that .list() returns a non-zero value for a subfolder both from the logcat output and from evaluating .list() at a breakpoint. When I step through the method, the current execution point correctly hits "return true;" but when I hit F7 to continue (I'm using IDEA), the execution point jumps to the last statement, "return false;", which is the value returned.
(I'm embarrassed to be asking). Why?
[EDIT] Request to show how I'm calling it - this method is not finished as I can't get the above to work!
public static String searchAssets(AssetManager asm, String path, String filename){
// TODO uses hard coded path separator
// search for the file, filename, starting at path path in the assets folder
// asm must be initialised by the caller using an application context
// returns an empty string for non existent files or for filename = ""
if (asm==null){return "";}
String foundFile; // return value
try {
// get a list of assets located at path
String[] files = asm.list(path);
// files may be null if an invalid path is passed
if (files!=null && files.length>0){
// loop through each asset for either a subfolder to search
// recursively or the file we are looking for
for (String file:files){
// <<<<<< HERE'S THE CALL >>>>>>>
if (isDirectory(asm,path + "/" + file)){
foundFile = searchAssets(asm,file,filename); // recurse this subfolder
// searchAssets returns either the name of our file, if found, or an empty string
if (!foundFile.equals("")){
return foundFile;
}
} else {
if (file.equals(filename)){
return path + "/" + file;
}
}
}
}
} catch (IOException e) {
// eat the exception - the caller did not set us up properly
}
return "";
}
[MORE EDITS]
Logcat:
09-27 09:21:12.047: DEBUG/GRENDLE(2811): harmonics_data/Harmonic Data SHC lists 2 assets
09-27 09:21:12.137: DEBUG/GRENDLE(2811): harmonics_data/Harmonic Data SHC is a subfolder, returning true
09-27 09:21:12.544: DEBUG/GRENDLE(2811): harmonics_data/Harmonic Data SHC is a not a subfolder, returning false
Here's a screenshot. The first breakpoint (return true;) is hit first. Continue stepping jumps straight to the last statement, return false, which is what is returned. This is NOT an exception. The exception breakpoint is never hit, and I don't expect it ever will, and as you can see from the logcat, the control flow seems wrong.
I don't know how it looks in Eclipse, but here the red lines are breakpoints and the blue line is the current execution point.
I've cleared the caches, deleted the file index, deleted the output folders and done a complete rebuild.
I really don't understand the log seeing the application, but I think that the problem is here:
// <<<<<< HERE'S THE CALL >>>>>>>
if (isDirectory(asm,path + "/" + file)){
foundFile = searchAssets(asm,path + "/" + file,filename); // recurse this subfolder
Maybe putting the path and the bar in the recursive call solve your problem, but, anyway, the isDirectory method is not necessary, I'll do the search method this way:
public static String searchAssets(AssetManager asm, String path,
String filename) {
// TODO uses hard coded path separator
// search for the file, filename, starting at path path in the assets
// folder
// asm must be initialized by the caller using an application context
// returns an empty string for non existent files or for filename = ""
if (asm == null) {
return "";
}
String foundFile = ""; // return value
try {
// get a list of assets located at path
String[] files = asm.list(path);
// files may be null if an invalid path is passed
if (files != null && files.length > 0) {
// loop through each asset for either a subfolder to search
// recursively or the file we are looking for
for (String file : files) {
foundFile = searchAssets(asm, path + "/" + file, filename); // recurse
// this
// subfolder
// searchAssets returns either the name of our file, if
// found, or an empty string
if(!foundFile.equals("")){
return foundFile;
}
}
} else {
if (path.equals(filename)) {
return path;
}else{
return "";
}
}
} catch (IOException e) {
// eat the exception - the caller did not set us up properly
}
return "";
}
First, don't use multiple exit points (returns), just make a boolean isDir and set it accordingly in your code and in the end return it.
Second, as I understand list()
will return a String[]
and if the folder is empty it will return null
(will NOT go to Exception as you don't catch NullPointerException
from [null].length).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With