Retrieving all Drawable resources from Resources object - android

In my Android project, I want to loop through the entire collection of Drawable resources. Normally, you can only retrieve a specific resource via its ID using something like:
InputStream is = Resources.getSystem().openRawResource(resourceId)
However, I want to get all Drawable resources where I won't know their ID's beforehand. Is there a collection I can loop through or perhaps a way to get the list of resource ID's given the resources in my project?
Or, is there a way for me in Java to extract all property values from the R.drawable static class?

Okay, this feels a bit hack-ish, but this is what I came up with via Reflection. (Note that resources is an instance of class android.content.res.Resources.)
final R.drawable drawableResources = new R.drawable();
final Class<R.drawable> c = R.drawable.class;
final Field[] fields = c.getDeclaredFields();
for (int i = 0, max = fields.length; i < max; i++) {
final int resourceId;
try {
resourceId = fields[i].getInt(drawableResources);
} catch (Exception e) {
continue;
}
/* make use of resourceId for accessing Drawables here */
}
If anyone has a better solution that makes better use of Android calls I might not be aware of, I'd definitely like to see them!

i used getResources().getIdentifier to scan through sequentially named images in my resource folders. to be on a safe side, I decided to cache image ids when activity is created first time:
private void getImagesIdentifiers() {
int resID=0;
int imgnum=1;
images = new ArrayList<Integer>();
do {
resID=getResources().getIdentifier("img_"+imgnum, "drawable", "InsertappPackageNameHere");
if (resID!=0)
images.add(resID);
imgnum++;
}
while (resID!=0);
imageMaxNumber=images.size();
}

I have taken Matt Huggins great answer and refactored it to make it more generic:
public static void loadDrawables(Class<?> clz){
final Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
final int drawableId;
try {
drawableId = field.getInt(clz);
} catch (Exception e) {
continue;
}
/* make use of drawableId for accessing Drawables here */
}
}
Usage:
loadDrawables(R.drawable.class);

You should use the Raw folder and AssetManager, but if you want to use drawables because why not, here is how...
Let's suppose we have a very long file list of JPG drawables and we want to get all the resource ids without the pain of retrieving one by one (R.drawable.pic1, R.drawable.pic2, ... etc)
//first we create an array list to hold all the resources ids
ArrayList<Integer> imageListId = new ArrayList<Integer>();
//we iterate through all the items in the drawable folder
Field[] drawables = R.drawable.class.getFields();
for (Field f : drawables) {
//if the drawable name contains "pic" in the filename...
if (f.getName().contains("image"))
imageListId.add(getResources().getIdentifier(f.getName(), "drawable", getPackageName()));
}
//now the ArrayList "imageListId" holds all ours image resource ids
for (int imgResourceId : imageListId) {
//do whatever you want here
}

Add a picture named aaaa and another named zzzz, then iterate through the following:
public static void loadDrawables() {
for(long identifier = (R.drawable.aaaa + 1);
identifier <= (R.drawable.zzzz - 1);
identifier++) {
String name = getResources().getResourceEntryName(identifier);
//name is the file name without the extension, indentifier is the resource ID
}
}
This worked for me.

If you find yourself wanting to do this you're probably misusing the resource system. Take a look at assets and AssetManager if you want to iterate over files included in your .apk.

I guess the reflection code will work but I don't understand why you need this.
Resources in Android are static once the application is installed so you can have a list of resources or an array. Something like:
<string-array name="drawables_list">
<item>drawable1</item>
<item>drawable2</item>
<item>drawable3</item>
</string-array>
And from your Activity you can get it by doing:
getResources().getStringArray(R.array.drawables_list);

Just do this:
Field[] declaredFields = (R.drawable.class).getDeclaredFields();

The OP wanted drawables and I needed layouts. This is what I came up with for layouts. The name.startsWith business lets me ignore system generated layouts, so you may need to tweak that a bit. This should work for any resource type by modifying the value of clz.
public static Map<String,Integer> loadLayouts(){
final Class<?> clz = R.layout.class;
Map<String,Integer> layouts = new HashMap<>();
final Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
String name = field.getName();
if (
!name.startsWith("abc_")
&& !name.startsWith("design_")
&& !name.startsWith("notification_")
&& !name.startsWith("select_dialog_")
&& !name.startsWith("support_")
) {
try {
layouts.put(field.getName(), field.getInt(clz));
} catch (Exception e) {
continue;
}
}
}
return layouts;
}

USE THIS MY CODE
R.drawable drawableResources = new R.drawable();
Class<R.drawable> c = R.drawable.class;
Field[] fields = c.getDeclaredFields();
for (int i = 0, max = fields.length; i < max; i++) {
final int resourceId;
try {
resourceId = fields[i].getInt(drawableResources);
// call save with param of resourceId
SaveImage(resourceId);
} catch (Exception e) {
continue;
}
}
...
public void SaveImage(int resId){
if (!CheckExternalStorage()) {
return;
}
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resID);
try {
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
OutputStream fOut = null;
File file = new File(path, "image1.png");
file.createNewFile();
fOut = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
MediaStore.Images.Media.insertImage(this.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
Log.i(LOGTAG, "Image Written to Exterbal Storage");
} catch (Exception e) {
Log.e("saveToExternalStorage()", e.getMessage());
}
}

To create an array of drawables in Kotlin:
val drawablesFields: Array<Field> = drawable::class.java.fields
val drawables: ArrayList<Drawable> = ArrayList()
for (field in drawablesFields) {
context?.let { ContextCompat.getDrawable(it, field.getInt(null)) }?.let {
drawables.add (
it
)
}
}

Related

Access assets files from another class

Sorry for my English. I have a class named Server and I need to read URL from a file in my applications assets but AssetManager android studio says it cannot be accessed from outside package and getassets() don't work neither. How can I access assets from not activity class?
How can I access assets from not activity class
To access assets you need Context. So pass one to your class (via constructor or other way) or just pass your URL if that's all you need from your assets
Non Activity Class
public CustomClass(Context myContext) {
AssetManager mngr = myContext.getAssets();
InputStream is = mngr.open("text.txt"); // get text file
try {
InputStream bitmap = myContext.getAssets().open("imagename.png");// get iamge file
Bitmap bit = BitmapFactory.decodeStream(bitmap);
//imgview.setImageBitmap(bit);
}
catch (IOException e1) {
e1.printStackTrace();
}
}
Call the class like as
CustomClass(getApplicationContext()) ; //activity
CustomClass(getActivity().getApplicationContext()); //fragment
I think getAssets only works within Activity Class. One of the ways to apply it in ordinary class is by creating constructor with Context parameter the reference getAssets within the constructor.
public DataFile(Context DataContext){
try {
AssetManager am = DataContext.getAssets();// If this line gives you ERROR then try AssetManager am=getActivity().getAssets();
InputStream mInpuStream = am.open("Question.xls");
Workbook mWorkBook = jxl.Workbook.getWorkbook(mInpuStream);
Sheet mSheet = mWorkBook.getSheet(0);
int mRow = mSheet.getRows();
int mCol = mSheet.getColumns();
String mContent = "";
for (int i = 0; i < mRow; i++) {
for (int c = 0; c < mCol; c++) {
Cell mCell = mSheet.getCell(c, i);
mContent = mContent + mCell.getContents();
}
mContent = mContent + "\n";
}
display(mContent);
} catch (Exception e) {
}
}

Importing multiple images in Android application

How can I import multiple images on my Android app? Can I assign single id to that bundle of images to bring it from drawable? Suggest me a way.
Currently I am only able to display one image multiple times in line layout. Here is the code line to bring the image:
placeholder = BitmapFactory.decodeResource(getResources(), R.drawable.picture2);
Should I enter multiple lines for picture3,picture4,...etc?
Simplest way I can think of:
int ids[] = new int[] {
R.drawable.picture2,
R.drawable.picture3,
R.drawable.picture4
};
Bitmap bitmaps[] = new Bitmap[ids.length];
for(int i = 0; i < ids.length; i += 1){
bitmaps[i] = BitmapFactory.decodeResource(getResources(), ids[i]);
}
Also you can re-write it as a function for improving modularity.
public Bitmap[] loadBitmaps(int ids[]){
Bitmap bitmaps[] = new Bitmap[ids.length];
for(int i = 0; i < ids.length; i += 1){
bitmaps[i] = BitmapFactory.decodeResource(getResources(), ids[i]);
}
return bitmaps;
}
Instead of Drawable store all images in Assets then you can get Image by passing name. Add following function in your activity.
private Bitmap getBitmapFromAsset(String paramString)
{
Object localObject = getResources().getAssets();
try
{
Bitmap ret = BitmapFactory.decodeStream(((AssetManager)localObject).open(paramString));
return ret;
}
catch (IOException ex)
{
ex.printStackTrace();
}
return null;
}

Android accessing drawable folder

I placed 10 images in drawable folder and I created a custom class which instances are holding an id Integer that should refer it to a image from draw folder. Now I wonder how to set those id-s at once, not one by one. Instead:
object[0].setImage(R.drawable.image1);
object[1].setImage(R.drawable.image2);
I want to do this with loop, but how?
Drawable ids as known are generated within static classes of final class R. So just use reflection to read the values of these static attributes. If you want to get the Int ids then use this code:
for(Field f : R.drawable.class.getDeclaredFields()){
if(f.getType() == int.class){
try {
int id = f.getInt(null);
// read the image from the id
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e){
e.printStackTrace();
}
}
}
Or if you want to search directly by images' names, you might be interested of the name attribute of fields like :
for(Field f : R.drawable.class.getDeclaredFields()){
if(f.getType() == int.class){
try {
String name = f.getName();
// rest of the code handling file loading
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
Doesn't work as far as I think.
There is code to get a drawable by its name. For example: "image"+myNumber"
Maybe: how to access the drawable resources by name in android
Be aware that the size of the view's list should match with the one that holds the ids:
public class HolderIDs {
public List<Integer> _ids;
public HolderIDs() {
_ids = new ArrayList<Integer>(Arrays.asList(R.drawable.one, R.drawable.two, R.ldrawable.three, R.drawable.four));
}
public List<Integer> getIDs() {
return _ids;
}
}
//Usage
List<ImageView> views = getYourViews();
List<Integer> ids = new HolderIDs().getIDs();
for (int i = 0; i < ids.size(); i++) {
View view = views.get(i);
if (view == null) return;
int id = ids.get(i);
view.setBackgroundResource(id);
}
You can create an integer array for the resources:
int resources = [ R.drawable.image1, R.drawable.image2, ...]
And use a bucle to set the resources into your object array.

List values in strings.xml

I would need to List all the values in strings.xml (for a given locale),
basically get a dynamic list of all the strings in an application.
My purpose here is to list all strings of all apps inside my (duely rooted) phone in order to speed up translation work.
I have no problem accessing the AssetManager of other apps :
-To get the list of all apps I use :
List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
-To access the package manager I use :
PackageManager manager = getPackageManager();
Resources mApk1Resources = manager.getResourcesForApplication(pname);
AssetManager a = mApk1Resources.getAssets();
But I am not quite sure where to go from here.
Obviously this is not for production purpose, just for helping my customer's translation team (you know Chinese OEMs...), so jackhammer-dirty solutions are welcome :-P (reflection, dynamic foreign context, live dex loading, dynamite etc...)
Thanks !
Edit 1 : I already know B.A.R.T it doesn't suit my need I need to do it on a live phone (not a zipped ROM) like a "live translation checker app". In particular, I don't have immediate access to the app's source codes, because I have to check a large number of phones, some being few years old. I can spend the time to root all of them if needed, but not much more.
Edit 2 : I really need something that runs on a live phone without the need of a PC. I can't modify the source code of individual apps and I can't decompile the ROM or use external tools like B.A.R.T I need an all-Java solution.
I can see that: usually the string for application label will get the first id in the resource strings. (not found an official document on this yet)
So the plan is: get the id of the label of an app, increase the id each time to get the next resource string until we get the Resources.NotFoundException
try {
List<ApplicationInfo> apps = getPackageManager()
.getInstalledApplications(0);
for (ApplicationInfo appInfo : apps) {
Resources mApk1Resources = getPackageManager()
.getResourcesForApplication(appInfo.packageName);
int id = appInfo.labelRes;
try {
Log.e("Test", "*******************************************");
Log.e("Test", apps.get(0).packageName);
while (true) {
Log.e("Test",
"String resource: "
+ mApk1Resources.getString(id));
id++;
}
} catch (Resources.NotFoundException e) {
// Handle exception
}
}
} catch (NameNotFoundException e) {
// Handle exception
}
Seeing you said you accept "jackhammer-dirty solutions", give this a try:
In your Strings.xml, surround all your String values with a <string-array> tag, and all string tags inside change to item tags, like so (used simple find-and-replace to replace the tag names):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World!</string>
<string name="app_name">YourAppNAme</string>
<string-array name="yourTitle">
<item>item1</item> //used to be <string name"blabla">....
<item>item2</item>
<item>item3</item>
</string-array>
</resources>
In your xml Layout file, where you have your ListView, put:
<ListView
android:id=”#+id/yourListView”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:entries="#array/yourTitle"
/>
Now, your Activity where you have your List, just call the ListView which should already be populated with the items from the Strings.xml
Don't forget to revert the changes in Strings.xml once you are done (and backup is always a good idea)!
Read more Here
Hope this helps!
Since you've rooted the phone and have access to every APK in the phone, how about just decompile them and get to the strings that way, see tutorial here: http://www.miui-au.com/add-ons/apktool/
Ok, I guess I found it. Reflection did the trick !
Root was not even needed. Crazy to know that any apps on your phone can see all the other's ressources...
public void listAllStrings(){
List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
for(int i=0;i<packs.size();i++) {
PackageInfo p = packs.get(i);
String pname = p.packageName;
Resources packageResources=null;
Context packageContext=null;
try
{
packageResources = MainActivity.this.getPackageManager().getResourcesForApplication(pname);
packageContext = MainActivity.this.createPackageContext(pname, Context.CONTEXT_INCLUDE_CODE + Context.CONTEXT_IGNORE_SECURITY);
}
catch(NameNotFoundException excep)
{
// the package does not exist. move on to see if another exists.
Log.e(pname, "Package not found!");
}
Class<?> stringClass=null;
try
{
// using reflection to get the string class inside the R class of the package
stringClass = packageContext.getClassLoader().loadClass(pname + ".R$string");
}
catch (ClassNotFoundException excep1)
{
// Less chances that class won't be there.
Log.e(pname, "R.string not found!");
}
if(stringClass!=null){
//For every fields of the string class
for( Field stringID : stringClass.getFields() )
{
try
{
//We get the id
int id = stringID.getInt(stringClass);
//We get the string value itself
String xmlResourceLayout = packageResources.getString(id);
Log.v(pname, xmlResourceLayout);
}
catch (Exception excep)
{
Log.e(pname, "Can't access : "+stringID.getName());
continue;
}
}
}
}
}
Hope this can help others :-)
Edit : For some Apks, the R class is not at the root of the package, so I had to write a find-R function
String findR(Context packageContext){
try {
//First case, the R class is easy to find !
packageContext.getClassLoader().loadClass(packageContext.getPackageName() + ".R");
return packageContext.getPackageName() + ".R";
} catch (Exception e) {
//Second case, it is not at the root of the package, we will list all classes...
Log.v(packageContext.getPackageName(),"R not found... Continue searching !");
try {
final PackageManager pm = getApplicationContext().getPackageManager();
ApplicationInfo ai = pm.getApplicationInfo(packageContext.getPackageName(), 0);
DexFile dx = DexFile.loadDex(ai.sourceDir, File.createTempFile("opt", "dex",
getCacheDir()).getPath(), 0);
String pathToR=null;
// Search inside each and every class in the dex file
for(Enumeration<String> classNames = dx.entries(); classNames.hasMoreElements();) {
String className = classNames.nextElement();
//for every single class, we will see if one of the fields is called app_name
//Log.v(className, "Class detail : "+className);
if(className.contains("R$string")) pathToR=className;
}
if(pathToR==null) throw new ClassNotFoundException();
pathToR=pathToR.replaceAll("$string", "");
Log.v(packageContext.getPackageName(), "R FOUND ! "+packageContext.getPackageName());
return pathToR;
} catch (Exception exc) {
Log.e(packageContext.getPackageName(), "ERROR ! R NOT FOUND ...");
return null;
}
}
}
But it still doesn't work in every case. So I ended hijacking the apktools library so it could run live on a phone... (I used the jar from 1.5.2 http://code.google.com/p/android-apktool/downloads/detail?name=apktool1.5.2.tar.bz2&can=2&q=) Here is my hijacked class :
public class Decoder {
public void decode(ResTable resTable, ExtFile apkFile, File outDir)
throws AndrolibException {
Duo<ResFileDecoder, AXmlResourceParser> duo = getResFileDecoder();
ResFileDecoder fileDecoder = duo.m1;
ResAttrDecoder attrDecoder = duo.m2.getAttrDecoder();
attrDecoder.setCurrentPackage(resTable.listMainPackages().iterator()
.next());
Directory inApk, in = null, out;
try {
inApk = apkFile.getDirectory();
out = new FileDirectory(outDir);
Log.v(MainActivity.SMALL_TAG,"Decoding AndroidManifest.xml with resources...");
fileDecoder.decodeManifest(inApk, "AndroidManifest.xml", out,
"AndroidManifest.xml");
// fix package if needed
adjust_package_manifest(resTable, outDir.getAbsolutePath()
+ "/AndroidManifest.xml");
if (inApk.containsDir("res")) {
in = inApk.getDir("res");
}
out = out.createDir("res");
} catch (DirectoryException ex) {
throw new AndrolibException(ex);
}
ExtMXSerializer xmlSerializer = getResXmlSerializer();
for (ResPackage pkg : resTable.listMainPackages()) {
attrDecoder.setCurrentPackage(pkg);
//Log.v(MainActivity.SMALL_TAG,"Decoding file-resources...");
//for (ResResource res : pkg.listFiles()) {
// fileDecoder.decode(res, in, out);
//}
Log.v(MainActivity.SMALL_TAG,"Decoding values */* XMLs...");
for (ResValuesFile valuesFile : pkg.listValuesFiles()) {
generateValuesFile(valuesFile, out, xmlSerializer);
}
generatePublicXml(pkg, out, xmlSerializer);
Log.v(MainActivity.SMALL_TAG,"Done.");
}
AndrolibException decodeError = duo.m2.getFirstError();
if (decodeError != null) {
throw decodeError;
}
}
public Duo<ResFileDecoder, AXmlResourceParser> getResFileDecoder() {
ResStreamDecoderContainer decoders = new ResStreamDecoderContainer();
decoders.setDecoder("raw", new ResRawStreamDecoder());
//decoders.setDecoder("9patch", new Res9patchStreamDecoder());
//TODO THIS DECODER CREATES ALL PROBLEMS !
AXmlResourceParser axmlParser = new AXmlResourceParser();
axmlParser.setAttrDecoder(new ResAttrDecoder());
decoders.setDecoder("xml", new XmlPullStreamDecoder(axmlParser,
getResXmlSerializer()));
return new Duo<ResFileDecoder, AXmlResourceParser>(new ResFileDecoder(
decoders), axmlParser);
}
public static final String PROPERTY_SERIALIZER_INDENTATION = "http://xmlpull.org/v1/doc/properties.html#serializer-indentation";
public static final String PROPERTY_SERIALIZER_LINE_SEPARATOR = "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator";
public static final String PROPERTY_DEFAULT_ENCODING = "DEFAULT_ENCODING";
public ExtMXSerializer getResXmlSerializer() {
ExtMXSerializer serial = new ExtMXSerializer();
serial.setProperty(PROPERTY_SERIALIZER_INDENTATION,
" ");
serial.setProperty(PROPERTY_SERIALIZER_LINE_SEPARATOR,
System.getProperty("line.separator"));
serial.setProperty(PROPERTY_DEFAULT_ENCODING, "utf-8");
serial.setDisabledAttrEscape(true);
return serial;
}
public void adjust_package_manifest(ResTable resTable, String filePath)
throws AndrolibException {
// check if packages different, and that package is not equal to
// "android"
Map<String, String> packageInfo = resTable.getPackageInfo();
if ((packageInfo.get("cur_package").equalsIgnoreCase(
packageInfo.get("orig_package")) || ("android"
.equalsIgnoreCase(packageInfo.get("cur_package")) || ("com.htc"
.equalsIgnoreCase(packageInfo.get("cur_package")))))) {
Log.v(MainActivity.SMALL_TAG,"Regular manifest package...");
} else {
try {
Log.v(MainActivity.SMALL_TAG,"Renamed manifest package found! Fixing...");
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(filePath.toString());
// Get the manifest line
Node manifest = doc.getFirstChild();
// update package attribute
NamedNodeMap attr = manifest.getAttributes();
Node nodeAttr = attr.getNamedItem("package");
mPackageRenamed = nodeAttr.getNodeValue();
nodeAttr.setNodeValue(packageInfo.get("cur_package"));
// re-save manifest.
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(filePath));
transformer.transform(source, result);
} catch (ParserConfigurationException ex) {
throw new AndrolibException(ex);
} catch (TransformerException ex) {
throw new AndrolibException(ex);
} catch (IOException ex) {
throw new AndrolibException(ex);
} catch (SAXException ex) {
throw new AndrolibException(ex);
}
}
}
private void generatePublicXml(ResPackage pkg, Directory out,
XmlSerializer serial) throws AndrolibException {
try {
OutputStream outStream = out.getFileOutput("values/public.xml");
serial.setOutput(outStream, null);
serial.startDocument(null, null);
serial.startTag(null, "resources");
for (ResResSpec spec : pkg.listResSpecs()) {
serial.startTag(null, "public");
serial.attribute(null, "type", spec.getType().getName());
serial.attribute(null, "name", spec.getName());
serial.attribute(null, "id",
String.format("0x%08x", spec.getId().id));
serial.endTag(null, "public");
}
serial.endTag(null, "resources");
serial.endDocument();
serial.flush();
outStream.close();
} catch (IOException ex) {
throw new AndrolibException("Could not generate public.xml file",
ex);
} catch (DirectoryException ex) {
throw new AndrolibException("Could not generate public.xml file",
ex);
}
}
private void generateValuesFile(ResValuesFile valuesFile, Directory out,
ExtXmlSerializer serial) throws AndrolibException {
try {
OutputStream outStream = out.getFileOutput(valuesFile.getPath());
serial.setOutput((outStream), null);
serial.startDocument(null, null);
serial.startTag(null, "resources");
for (ResResource res : valuesFile.listResources()) {
if (valuesFile.isSynthesized(res)) {
continue;
}
((ResValuesXmlSerializable) res.getValue())
.serializeToResValuesXml(serial, res);
}
serial.endTag(null, "resources");
serial.newLine();
serial.endDocument();
serial.flush();
outStream.close();
} catch (IOException ex) {
throw new AndrolibException("Could not generate: "
+ valuesFile.getPath(), ex);
} catch (DirectoryException ex) {
throw new AndrolibException("Could not generate: "
+ valuesFile.getPath(), ex);
}
}
private String mPackageRenamed = null;
}
and here's how I use it :
String pname = p.packageName;
Context packageContext = MainActivity.this.createPackageContext(pname, Context.CONTEXT_INCLUDE_CODE + Context.CONTEXT_IGNORE_SECURITY);
ApplicationInfo ai = packageContext.getApplicationInfo();
Log.v(TAG,"Analysing : "+pname+" "+ai.sourceDir);
if(new File(destination.getAbsolutePath()+"/"+pname+".strings.xml").exists()){
Log.v(TAG,"Already translated...");
continue;
}
ApkDecoder decoder = new ApkDecoder();
decoder.setApkFile(new File(ai.sourceDir));
File directory = new File(Environment.getExternalStorageDirectory()+File.separator+"tempApk");
directory.mkdirs();
DeleteRecursive(directory);
directory.mkdirs();
decoder.setOutDir(directory);
decoder.setForceDelete(true);
File frmwrk = new File(Environment.getExternalStorageDirectory()+File.separator+"framework");
frmwrk.mkdirs();
decoder.setFrameworkDir(Environment.getExternalStorageDirectory()+File.separator+"framework");
decoder.setDecodeSources((short)0x0000);
decoder.setKeepBrokenResources(true);
try{
//decoder.decode();
new Decoder().decode(decoder.getResTable(), new ExtFile(new File(ai.sourceDir)), directory);
} catch (Throwable e) {
e.printStackTrace();
}
Lots of headaches for few Strings ;-)

Bluetooth folder, different path on different phones

I found out that different versions of android puts the received bluetooth files in different folder. For instance, one of my test phones running android 2.2 saves the files to this path:
/mnt/sdcard/Downloads/Bluetooth
and my second test phone, running android 4.0 saves the files here
/mnt/sdcard/Bluetooth
Is this operating system "issue" or is it set from the manufacture of the phone?
If the first statement is the correct can I check which version of android running, and the point to the bluetooth folder? Or is there a much simpler way to do this?
Thanks!
After some hours I made two methods for doing this. You should put the methods in a AsyncTask or a Thread. So here is my two methods:
public List<File> folderSearchBT(File src, String folder)
throws FileNotFoundException {
List<File> result = new ArrayList<File>();
File[] filesAndDirs = src.listFiles();
List<File> filesDirs = Arrays.asList(filesAndDirs);
for (File file : filesDirs) {
result.add(file); // always add, even if directory
if (!file.isFile()) {
List<File> deeperList = folderSearchBT(file, folder);
result.addAll(deeperList);
}
}
return result;
}
This is a recursive method which will add all folders in the src parameter into a List.
I use this method in this method here:
public String searchForBluetoothFolder() {
String splitchar = "/";
File root = Environment.getExternalStorageDirectory();
List<File> btFolder = null;
String bt = "bluetooth";
try {
btFolder = folderSearchBT(root, bt);
} catch (FileNotFoundException e) {
Log.e("FILE: ", e.getMessage());
}
for (int i = 0; i < btFolder.size(); i++) {
String g = btFolder.get(i).toString();
String[] subf = g.split(splitchar);
String s = subf[subf.length - 1].toUpperCase();
boolean equals = s.equalsIgnoreCase(bt);
if (equals)
return g;
}
return null; // not found
}
Hope this helps, guys!

Categories

Resources