I am building an android library project which need some static resources(images/xml and etc) internally.
Then I wonder where I can put these resources and how to access them?
Since I put the resources in the assets folder. And I use the AssetManager to access the resources:
public class DataProvider {
byte[] getDrawableData(int num) {
AssetManager am = Resources.getSystem().getAssets();
InputStream is = null;
try {
is = am.open("t.jpg");
} catch (IOException e) {
return "".getBytes();
}
if (is != null) {
Drawable dw = Drawable.createFromStream(is, null);
Bitmap bm = ((BitmapDrawable) dw).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
return "".getBytes();
}
}
However I got the error: W/System.err(19583): java.io.FileNotFoundException: t.jpg
What is the problem?
As Sankar V said the library project does not support the raw assets. Then It seems that I have to put the resurces under the res folder.
But I have tried to use the Resources.getSystem().getResources().... method which can not get what I want. And people said that this method can only get the system level resources rather than the application level resources.
If this is the truth. Does it mean that I have to hold a reference of the Context object anywhere I want to get any resources?
Then I wonder where I can put these resources and how to access them?
From Android Doc's
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.
Docs Reference Link : LibraryProjects
Solution : How to access resource files saved in res/ directory of library project from application project
Note : If you want to access the resources from Library Project itself add the resources to res/ directory not in assets. Because the files in assets won't be bundled with the .jar file.
You can access it as usual using the reference generated in R.java file.
Ex: To access a image from drawable use
R.drawable.image_name
Does it mean that I have to hold a reference of the Context object anywhere I want to get any resources?
Really you should hold a reference to context to access the resources
Update:
Now Android library project can be generated as aar (Android Archive) file which allows you to bundle the resource files needed for the library project instead of the old jar (Java Archive) file which only allow you to bundle Java classes.
Or you can use a Linked Folder in Eclipse, and link your assets folder across to your new project.
Okay, its been a while since a working solution has been given to this question. I have been working with creating Android library for few days, and encountered this problem myself as well. I tried all the above solutions put forward, but none of them worked for me.
Recently I watched a video on Android library, and got a glimpse of the solution, even though it was not mentioned that it is necessary for using res directory resources inside library code.
So the solution is simple.
Simply, you can check if following line
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourpackage"> <!-- this line -->
</manifest>
is present in your manifest. Otherwise you won't be able to use any of the strings, styles, drawables in your library java files/xml files.
I have checked this on my end, and found this solution randomly, after searching online for nearly 2 days.
Try it and tell me if it works.
Related
I use some class. That's constructor needs some file path that contains some files.
ex)
Komoran komoran = new Komoran("D:\program_project\lib");
Now I'm making android app. so I can't use absolute path (Because other people who download my app don't have that folder and files)
so I decide to use 'assets' folder that is maybe in APK file. So, final code is like below.
Komoran komoran = new Komoran("file:///android_asset");
but It seems like folder path is wrong(this class doesn't work). What I did wrong ?
This "file:///android_asset" path is used for applications which uses webview ex. cordova/phonegap. As it is part of resources because when Apk is created you can not use this path to access your assets folder. You have to work with context.getResources().getAssets().open("fileName")this code only.
Maybe u can add this code:
context.getResources().getAssets().open("fileName").
u will get a inputstream, and u can do something u want.
No need to use getResources.
You can use directly
context.getAssets().open("fileName").
In Android Studio, I need to use some resources (image, audio, etc...) from a folder different from the standard 'res',
Let's suppose that I have:
the '_Resources' folder containing the image 'aaa.png' .
the standard 'res' folder containing the image 'bbb.png'
I have put inside gradle file:
android {
sourceSets {
main.resources.srcDirs += 'C:/..../myLibrary/src/_Resources'
}
}
After that I see in Android window (top left of Android Studio) correctly both the standard 'res' folder and the 'resources' folder.
if I have to access to 'bbb.png' of 'res' standard folder, I use:
import com.myproject.R
.....
int xxx = R.drawable.bbb
THE QUESTION IS:
how can access now to aaa.png?
It is not seen in R. ; so I tried to import something else, but what?
Thank you in Advance
Fausto
This is not possible. If you define two png file with the same name in multiple resource folders android will load just one of them (not sure which one).
The name of them are actually their ID. And the concept of ID is sensful if its unique. So you cant do this.
Having multiple resource folders is just something to separate files and make everything more clear and better. Just foldering and nothing more.
for those that could have the same problem:
I didn't have success in accessing to resource folder, but I found another solution that fits my needs:
I added the '_Resources' folder in Assets, writing in gradle file:
main.assets.srcDirs += 'C:/..../myLibrary/src/_Resources'
then I get access in code to resources by:
AssetManager assetManager = getAssets();
InputStream myInputStream = assetManager.open("aaa.png");
That's all...
I have some level definitions in xml format (with .txt extension) inside (without any subfolders) my project's rescources folder
I for more scalability, I have a plain text file naming all these level definition XMLs
I read that file using
TextAsset WorldList = (TextAsset)Resources.Load("WorldList");
And then I load the needed world:
TextAsset TA = (TextAsset)Resources.Load(/*"LevelDefs/" +*/ Worlds[worldToload]);
xps.parseXml(TA.text);
loadLevel(levelToLoad);
(you see that I have moved these rescources out of subfolder to reduce the chance of them not loading)
worldToload here is the index number of that world
program works fine on windows but nothing loads on my android test device.
I seem to have problems debugging on device so I only guess something went wrong in loading phase.
any suggestions?
From Unity Documentation:
Most assets in Unity are combined into the project when it is built.
However, it is sometimes useful to place files into the normal
filesystem on the target machine to make them accessible via a
pathname. An example of this is the deployment of a movie file on iOS
devices; the original movie file must be available from a location in
the filesystem to be played by the PlayMovie function.
Any files placed in a folder called StreamingAssets in a Unity project
will be copied verbatim to a particular folder on the target machine.
You can retrieve the folder using the Application.streamingAssetsPath
property. It’s always best to use Application.streamingAssetsPath to
get the location of the StreamingAssets folder, it will always point
to the correct location on the platform where the application is
running.
So below snippet should work:
// Put your file to "YOUR_UNITY_PROJ/Assets/StreamingAssets"
// example: "YOUR_UNITY_PROJ/Assets/StreamingAssets/Your.xml"
if (Application.platform == RuntimePlatform.Android)
{
// Android
string oriPath = System.IO.Path.Combine(Application.streamingAssetsPath, "Your.xml");
// Android only use WWW to read file
WWW reader = new WWW(oriPath);
while ( ! reader.isDone) {}
realPath = Application.persistentDataPath + "/Your"; // no extension ".xml"
var contents = System.IO.File.ReadAll(realPath);
}
else // e.g. iOS
{
dbPath = System.IO.Path.Combine(Application.streamingAssetsPath, "Your.xml");
}
Thanks to David I have resolved this problem.
for more precision I add some small details:
1-As David points out in his answer (and as stated in unity documentations), we should use StreamingAssets if we want to have the same folder structure. One should use Application.streamingAssetsPathto retrieve the path.
However, files are still in the apk package in android's case, so they should be accessed using unity android's www class.
a good practice here is to create a method to read the file (even mandatory if you are going to read more than one file)
here is one such method:
private IEnumerator LoadDataFromResources(string v)
{
WWW fileInfo = new WWW(v);
yield return fileInfo;
if (string.IsNullOrEmpty(fileInfo.error))
{
fileContents = fileInfo.text;
}
else
fileContents = fileInfo.error;
}
This is a coroutine, and to use it we need to call it using
yield return StartCoroutine(LoadDataFromResources(path + "/fileName.ext"));
Yet another remark: we can not write into this file or modify it as it's still inside the apk package.
I try to use OpenNLP in an Android application with eclipse, and I imported the 4 JARs into the libs folder.
It's probably a stupid question.. but where should I put the model files "en-pos-maxent.bin"? I can't find anything regarding the path anywhere
I try to run the code contains this line:
POSModel model = new POSModelLoader()
.load(new File("en-pos-maxent.bin"));
I tried putting the en-pos-maxent.bin inside a new folder within the project("tagger/en-pos-maxent.bin"), inside the libs folder, or simply give the path where the en-pos-maxent.bin is put when downloaded("Users/ariel/Downloads/en-pos-maxent.bin"), it always give me the error: POS Tagger model file does not exist path: (the path I typed in)
Could anybody help please?
When you use new File("filename") the file is expected to be in the current working directory, I don't think that's different on Android. You can use System.getProperty("user.dir") to get the current working directory. It's by default the directory you start the program from. You could also specify a full path like new File("/full/path/filename") instead.
In android the right way to add file to the application (inside APK) is to put into the assets folder. Then you can't get File object from assets folder but, you can create that File using a buffer or in you case just get it into the InputStream. For example if you will create models folder into the assets folder (assets/models), your code will look like this:
AssetManager am = getAssets();
InputStream inputStream = am.open("models/en-pos-maxent.bin");
POSModel posModel = new POSModel(inputStream);
So, I've seen many posts on this, but none has helped. I want to work with the assets folder, for organizational purposes. The images below show where the 'assets' folder is, along with the app.imi options of where it should be. I have tested this, and in the >exploded-aar/com../appcompat-v7/19.1.0/assets ... the files inside this seem to work. I can call on the .mp3 file and load and play it correctly (Though a few times it did not recognize it. Even when it was inside a folder, inside of the directory.)
In the src/main/assets folder, all the files are ignored. Is there a specific way I have to call this? In other words, must I also link the actual folder it is it? src/main/assets/music to load up the riseofcc.mp3?
I do not have 10 reputation to post images, so sorry for only links.
EDIT:Also I am using Android Studio 0.5.7
ANSWERED:
Thanks for Xavier Duchrohet for explaining exploded-aar is for the application's dependencies. I have learned that when calling upon a file inside your asset's folder using the code:
AssetManager assetManager = getAssets();
InputStream inputStream = null;
AssetFileDescriptor descriptor = assetManager.openFd("sound/explosion.ogg");
You must include the folder's parent inside the arguement.
Android Studio's app.iml has the asset's directory (src/main/assets) inside of its configuration's options.
Normally, to include sound files, I create a folder called raw, inside the app / src / main / res.
That is, I right click on the folder res and from the menu that appears, choose: New / Android Resource Diretory. Renaming in the window that appears, the Directory name field values for raw.
How it works for me, I hope this might have helped him.