Android: load PropertyResourceBundle with variable name - java

I´m trying to load ".properties" files into a PropertyResourceBundle object
It´s working with this code, but I have to load a lot of different combinations.
static ResourceBundle res[] = {null, null, null};
res[i] = new PropertyResourceBundle(getResources().openRawResource(R.raw.respaul_de));
These files are in res/raw/ directory of my android project.
Does someone knows a solution to do it like that...
res[i] = new PropertyResourceBundle(getResources().openRawResource("R.raw." + <nameArray> + <languageArray>));
I´ve tried it like that...but it didn´t work. Because I get always an ID of "0".
int resID = getResources().getIdentifier("respaul_de", "id", getPackageName());
res[i] = new PropertyResourceBundle(getResources().openRawResource(resID));
I would be pleased if someone can help me.
EDIT:
Solution:
String n = resourceNames[i / 3].toLowerCase() + "_" + (lang[i % 3].toString()).toLowerCase();
int is = getResources().getIdentifier(n, "raw", getPackageName());
res[i] = new PropertyResourceBundle(getResources().openRawResource(is));
resolved:
int is = getResources().getIdentifier("respaul_en", "raw", getPackageName());

Related

How to get variables from AndroidJavaObject into a C# class using Unity3D

I can't find how to get ListArray variables from an AndroidJavaObject in C#.
I'm trying to make a for function using a Count for the number of items in the ListArray that is stored as an AndroidJavaObject. But I need to know how to get the Count from the AndroidJavaObject and how to use it properly.
This is what I'm using to get the variables, also notice that "packages" is not an AndroidJavaObject[].
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");
int flag = new AndroidJavaClass("android.content.pm.PackageManager").GetStatic<int>("GET_META_DATA");
AndroidJavaObject pm = currentActivity.Call<AndroidJavaObject>("getPackageManager");
AndroidJavaObject packages = pm.Call<AndroidJavaObject>("getInstalledApplications", flag);
it's very rudimentary at this point, but it works thanks to some help from this How to get installed apps list with Unity3D?
The progress thus far stalls at getting the icon, everything else works perfect, I need a way to get either a string that links to the icon somehow, or the Texture2D of the icon. Another alternative would be a to use a AndroidJavaObject that contains a drawable as if it's a Texture2D. I have no idea how to accomplish any of this though.Another Idea I had was to convert it to another variable, like byte[] that can be transferred and converted back, but I have yet to find a method of that which works under the circumstance.
int count = packages.Call<int>("size");
AndroidJavaObject[] links = new AndroidJavaObject[count];
string[] names = new string[count];
Texture2D[] icons = new Texture2D[count];
int ii =0;
for(int i=0; ii<count;){
//get the object
AndroidJavaObject currentObject = packages.Call<AndroidJavaObject>("get", ii );
try{
//try to add the variables to the next entry
links[i] = pm.Call<AndroidJavaObject>("getLaunchIntentForPackage", currentObject.Get<AndroidJavaObject>("processName"));
names[i] = pm.Call<string>("getApplicationLabel", currentObject);
icons[i] = pm.Call<Texture2D>("getApplicationIcon", currentObject);
Debug.Log ("(" + ii + ") " + i +" "+ names[i]);
//go to the next app and entry
i++;
ii++;
}
catch
{
//if it fails, just go to the next app and try to add to that same entry.
Debug.Log("skipped "+ ii);
ii++;
}
}
I really hate to ask two questions in a row here, and I apologize for having to do so, but this is a difficult and seemingly awkward circumstance, that has little to no documentation (that I can find).
First of all the docs on the interop between Unity3D and Android are scarce at best.
The most important thing is that the only interface Unity exposes to work with java object is AndroidJavaObject and that interface has only a couple of methods defined. You can only use those ones and only those.
This means that you don't get a Count object when working with an java array and you'll still be working with AndroidJavaObject.
int count = packages.Call<int>("size"); //getting the size of the array
for( int i = 0; i < count; i++ )
{
//getting the object at location i
AndroidJavaObject currentObject = packages.Call("get", i );
//use currentObject using the same methods as before: Call, CallStatic, Get, GetStatic
}
I know this is verbose, and writing code like this is hard to test, you need to make and apk and deploy it to a device to check that it runs.
Probably a faster way of doing this is to make your own java class that does all this on the java side and expose one method that gets called from the Unity side. This way at least you get the benefit of static typing when making a jar that you'll add in the Plugins/Android folder.
I'm trying to do the same thing here, but my launcher must only show the CardBoard apps. What i've decided is to make a library in java and import it to Unity as a plugin:
This is my Java class:
public class Launcher extends UnityPlayerActivity {
private List<ApplicationInfo> cbApps;
#Override
protected void onStart() {
super.onStart();
PackageManager pm= getPackageManager();
List<ApplicationInfo> lista = pm.getInstalledApplications(PackageManager.GET_META_DATA);
cbApps= new LinkedList<ApplicationInfo>();
for(ApplicationInfo ai : lista){
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
intentToResolve.addCategory("com.google.intent.category.CARDBOARD");
intentToResolve.setPackage(ai.packageName);
if(pm.resolveActivity(intentToResolve, 0)!=null) {
cbApps.add(ai);
}
}
}
public int getListSize(){
return cbApps.size();
}
And here my C# method:
void Start () {
AndroidJavaClass unity = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject> ("currentActivity");
texto.text=""+currentActivity.Call<int> ("getListSize");
}
This way I can create in Java every method that I need to acces the list. The problem I'm still having is trying to get the Texture2D of the icons. I've tried returning the Drawable from Java and accesing with a Call just as you did, but it doesn't work at all. I've been 2 days working with that, I'll let you know if I find a solution.
EDIT:
Finally I could get the images:
First in Java I created this method:
public byte[] getIcon(int i) {
BitmapDrawable icon= (BitmapDrawable)context.getPackageManager().getApplicationIcon(cbApps.get(i));
Bitmap bmp = icon.getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
return byteArray;
}
That way I can access the Byte array representing the Drawable from Unity and show it as the main texture of a Plane:
void Start () {
using (AndroidJavaClass unity = new AndroidJavaClass ("com.unity3d.player.UnityPlayer")) {
context = unity.GetStatic<AndroidJavaObject> ("currentActivity");
}
using (AndroidJavaClass pluginClass=new AndroidJavaClass("com.droiders.launcher.Launcher")) {
launcher= pluginClass.CallStatic<AndroidJavaObject>("getInstance", context);
byte[] bytes= launcher.Call<byte[]>("getIcon",0);
Texture2D tex= new Texture2D(2,2);
tex.LoadImage(bytes);
plane.GetComponent<Renderer>().material.mainTexture=tex;
}
}
Hope it helps you. It's been hard but this beast has been tamed :P
Also thanks you all for your ideas.

Open Office 1.1.4 Export to PDF with background images using java

I have a problem that needs solving where we use OpenOffice 1.1.4 templated reports and programmatically export them to PDF.
The team who create the templates have recently changed the header image and some images in a table to background images (before they were just inserted) since this change the current program is not creating the PDFs with the images. We can export from OpenOffice manually and the images are included. Can anyone help with a change I may need to make to get these background images included please?
The current code:
private void print(XInterface xComponent,
PrintRequestDTO printReq, File sourceFile,
Vector<String> pages) throws java.lang.Exception {
String pageRange;
// XXX create the PDF via OOo export facility
com.sun.star.frame.XStorable pdfCreator = (com.sun.star.frame.XStorable) UnoRuntime
.queryInterface(
com.sun.star.frame.XStorable.class,
xComponent);
PropertyValue[] outputOpts = new PropertyValue[2];
outputOpts[0] = new PropertyValue();
outputOpts[0].Name = "CompressionMode";
outputOpts[0].Value = "1"; // XXX Change this perhaps?
outputOpts[1] = new PropertyValue();
outputOpts[1].Name = "PageRange";
if (printReq.getPageRange() == null) {
pageRange = "1-";
}
else {
if (printReq.getPageRange().length() > 0) {
pageRange = printReq.getPageRange();
}
else {
pageRange = "1-";
}
}
log.debug("Print Instruction - page range = "
+ pageRange);
PropertyValue[] filterOpts = new PropertyValue[3];
filterOpts[0] = new PropertyValue();
filterOpts[0].Name = "FilterName";
filterOpts[0].Value = "writer_pdf_Export"; // MS Word 97
filterOpts[1] = new PropertyValue();
filterOpts[1].Name = "Overwrite";
filterOpts[1].Value = new Boolean(true);
filterOpts[2] = new PropertyValue();
filterOpts[2].Name = "FilterData";
filterOpts[2].Value = outputOpts;
if (pages.size() == 0) { // ie no forced page breaks
// set page range
outputOpts[1].Value = pageRange;
filterOpts[2] = new PropertyValue();
filterOpts[2].Name = "FilterData";
filterOpts[2].Value = outputOpts;
File outputFile = new File(
sourceFile.getParent(),
printReq.getOutputFileName()
+ ".pdf");
StringBuffer sPDFUrl = new StringBuffer(
"file:///");
sPDFUrl.append(outputFile.getCanonicalPath()
.replace('\\', '/'));
log.debug("PDF file = " + sPDFUrl.toString());
if (pdfCreator != null) {
sleep();
pdfCreator.storeToURL(sPDFUrl.toString(),
filterOpts);
}
}
else if (pages.size() > 1) {
throw new PrintDocumentException(
"Only one forced split catered for currently");
}
else { // a forced split exists.
log.debug("Page break found in "
+ (String) pages.firstElement());
String[] newPageRanges = calculatePageRanges(
(String) pages.firstElement(), pageRange);
int rangeCount = newPageRanges.length;
for (int i = 0; i < rangeCount; i++) {
outputOpts[1].Value = newPageRanges[i];
log.debug("page range = " + newPageRanges[i]);
filterOpts[2] = new PropertyValue();
filterOpts[2].Name = "FilterData";
filterOpts[2].Value = outputOpts;
String fileExtension = (i == 0 && rangeCount > 1) ? "__Summary.pdf"
: ".pdf";
File outputFile = new File(
sourceFile.getParent(),
printReq.getOutputFileName()
+ fileExtension);
StringBuffer sPDFUrl = new StringBuffer(
"file:///");
sPDFUrl.append(outputFile.getCanonicalPath()
.replace('\\', '/'));
log.debug("PDF file = " + sPDFUrl.toString());
if (pdfCreator != null) {
log.debug("about to create the PDF file");
sleep();
pdfCreator.storeToURL(
sPDFUrl.toString(), filterOpts);
log.debug("done");
}
}
}
}
Thanks in advance.
Glad that suggestion of making the document visible helped. Since it has ALSO fixed the problem you have a timing/threading issue. I suspect you'll find that another dodgy option of doing a sleep before executing the save to PDF will also allow the images to appear. Neither of these solutions is good.
Most likley best fix is to upgrade to a newer version of Open Office (the API calls you have should still work). Another option would be to try to call the API to ask the document to refresh itself.
After finding the correct property I was able to open the file with the hidden property set to false, this meant when the file was exported to PDF it included the background images. Its a shame I could not find another solultion that kept the file hidden but at least its working.

Android: How to retrieve file name and extension of a resource by resource ID

I have the following:
getResources().getResourceEntryName(resourceId);
The problem is, that it retrieves only the file name without the extension.
For example, if I have the following res/drawable/pic.jpg, the
getResources().getResourceEntryName(resourceId);
is returning the value "pic". The extension .jpg is missing.
To get "res/drawable/pic.jpg" you could use this:
TypedValue value = new TypedValue();
getResources().getValue(resourceId, value, true);
// check value.string if not null - it is not null for drawables...
Log.d(TAG, "Resource filename:" + value.string.toString());
// ^^ This would print res/drawable/pic.jpg
Source: android/frameworks/base/core/java/android/content/res/Resources.java
You can do so
Field[] fields = R.raw.class.getFields();
for (int count = 0; count < fields.length; count++) {
// Use that if you just need the file name
String filename = fields[count].getName();
Log.i("filename", filename);
int rawId = getResources().getIdentifier(filename, "raw", getPackageName());
TypedValue value = new TypedValue();
getResources().getValue(rawId, value, true);
String[] s = value.string.toString().split("/");
Log.i("filename", s[s.length - 1]);
}
This should be the best solution:
TypedValue value = new TypedValue();
getResources().getValue(resourceId, value, true);
String resname = value.string.toString().substring(13, value.string.toString().length());
resname = "pic.jpg"
Short answer: You can't.
Another way to do this, would be to put your graphics inside the assets folder.
Then you can access the Files directly, without your App needing any permission.
You can, for example, do so in your Activity:
AssetManager am = this.getApplicationContext().getAssets()
InputStream is = am.open(foldername+"/"+filename)
Bitmap myNewImage = BitmapFactory.decodeStream(is);
I hope that this will accomplish what you had in mind.
UPDATE: it seems it is indeed possible, see Aleksandar Stojiljkovic's answer instead.

Using a String to change a Bitmap

I have the following problem:
String explosion_type = this.prefs.getString("explosion_type", "ring_explosion");
BitmapFactory.Options optionsExplosion = new BitmapFactory.Options();
optionsExplosion.inPurgeable = true;
this._explosionSprite = BitmapFactory.decodeResource(_context.getResources(),
com.forwardapps.liveitems.R.drawable.explosion, optionsExplosion);
I'm trying to use a String in place of the resource name, that way I can hotswap resources in the preference menu. This method causes the app to crash.
What is the proper way of implementing a situation like this? (Without making it too complicated or using if statements)
Use method getIdentifier on Resources object to fetch id of a drawable:
String explosion_type = this.prefs.getString("explosion_type", "ring_explosion");
Log.i("imagename", explosion_type);
BitmapFactory.Options optionsExplosion = new BitmapFactory.Options();
optionsExplosion.inPurgeable = true;
int imageResource = getResources().getIdentifier(explosion_type, "drawable", getPackageName());
this._explosionSprite = BitmapFactory.decodeResource(_context.getResources(), imageResource, optionsExplosion);

Getting resource from name instead of id in android

I have the following code for getting a resource using name instead of id:
spec = new ImageView[56];
for (i=2; i<=56; i++) {
String s = null;
s = "items_r"+Integer.toString(i)+"_c1";
spec[i] = (ImageView) findViewById(getResources().getIdentifier(s,"drawable",getPackageName()));
Log.e(tag, Boolean.toString(spec[i] == null));
}
I have 56 items in my drawable folder named items_r1_c1 to items_r56_c1;
But I am getting spec[i] as null.
Could someone point me towards my error and how to correct it?
Thank you.
findViewById(int) is for finding Views that have already been inflated and that currently exist under your Activity's content view.
You'll want to use Resources.getDrawable(int) or ImageView.setImageResource(int).
spec = new ImageView[56];
for (i=2; i<=56; i++) {
String res = "items_r" + Integer.toString(i) + "_c1";
int resId = getResources().getIdentifier(res, "drawable", getPackageName());
spec[i] = new ImageView();
// Drawable image = getResources.getDrawable(resId);
// spec[i].setImageDrawable(image);
spec[i].setImageResource(resId);
Log.e(tag, Boolean.toString(spec[i] == null));
}
Try this
int id = findViewById(getResources().getIdentifier(s,"drawable",getPackageName());
spec[i] = (new ImageView()).setImageResource(id);

Categories

Resources