Access resources from Android library - android

I'm using Android Studio 2.0 and I've created an Android library to keep some classes and a XML data file. The file is placed in the /res directory but I cannot find any way to access it. I always get a FileNotFoundException.
The code I use to open and serialize the file is:
try {
SomeClass someClass = new SomeClass();
someClass.entries = new ArrayList<SomeEntry>();
Serializer serializer = new Persister();
InputStream file=assetManager.open("simple.xml");
someClass= serializer.read(SomeClass.class, file);
}
catch (Exception ex)
{
ex.getMessage();
}

simple.xml should be inside assets folder.
And make sure that assetManager object is equal to getApplicationContext().getAssets().open("simple.xml");

Related

assets folder structure in cordova

I'm trying to read the text file in cordova. For this I've created a assets folder (See the cordova folder structure image) and placed my text file in that but i'm getting the error java.io.FileNotFoundException: json.txt.
Note:
When i tried it in the Android native I'm able to read the file...
Code
String yourData = LoadData("json.txt");
public String LoadData(String inFile) {
String tContents = "";
try {
InputStream stream = context.getAssets().open(inFile);
int size = stream.available();
byte[] buffer = new byte[size];
stream.read(buffer);
stream.close();
tContents = new String(buffer);
} catch (IOException e) {
e.printStackTrace();
Log.e("catch", e + "");
}
return tContents;
}
Cordova folder structure
Am i placing assets folder in the wrong position or am i doing any other mistake?
Actual problem was, haven't mentioned assets folder in plugin.xml. After mentioning it everything working fine
plugin.xml entry
<source-file src="json.txt" target-dir="assets"/>
and use same method and structure which is in the question
Well as i got to know Cordova access your file as a relative path. and it will assume you're using the www directory.
so if you want to access your file you can do like this below in Cordova plugin -
window.resolveLocalFileSystemURI("file:///android_asset/www/json.txt", onResolveSuccess, onFail);
your file path will become something like this -
file:///android_asset/www/json.txt"

not found as file or resource in assets folder

I have a question, why can't access a file in my assets folder?
Folder
My code
Uri path = Uri.parse("android.resource://com.hackro.tutorials.myapplication/raw/comprobante.pdf");
String newPath = path.toString();
Resources res = getResources();
try {
PdfReader reader = new PdfReader(newPath);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("/sdcard/evidencia.pdf"));
AcroFields fields = stamper.getAcroFields();
fields.setField("Referencia", referencia);
fields.setField("Fecha y Hora", fechahora);
fields.setField("Tipo", tipo);
fields.setField("Operacion", operacion);
fields.setField("no. tarjeta", tarjeta);
fields.setField("vencimiento", vencimiento);
fields.setField("monto", monto);
fields.setField("concepto", concepto);
fields.setField("Nombre", nombre);
fields.setField("Autorizacion", autorizacion);
stamper.setFormFlattening(true);
stamper.close();
reader.close();
} catch (Exception e) {
Log.e("error: ", e.getMessage());
}
Exception
java.io.IOException: android.resource://com.hackro.tutorials.myapplication/raw/comprobante.pdf not found as file or resource.
You have a few problems here.
First, resources are not assets. You are attempting to use the android.resource scheme to access an asset as if it were a raw resource, and this will not work.
Second, you are constructing a Uri, then are converting that to a string, then are trying to wrap that in a File object. That will never work, for any type of Uri.
Third, neither resources nor assets are files on the filesystem of the device. They are files on the filesystem of your development machine. They are entries in the APK file on the device. You cannot get a File object pointing to a resource or an asset.
Use getAssets() on a Context (e.g., your Activity or Service) to get an AssetManager. Then, call open("comprobante.pdf") on that AssetManager to get an InputStream on the asset. Pass that to the PdfReader constructor and hope that your PDF library supports an InputStream.

Can you create a .dat file in Android

I am trying to write my first app for Android. I knew Java formerly but it has been a year or two since I used it.
I want to create a simple file in internal storage - I understand I do not have to set any permissions to create such a file?
Is it a .dat file I need if I want to save an ArrayList? Does Android require me to use file extension when creating it?
Even with just trying the basic file creation - checking for existence of file and then creating it if it does not exist - does not work. Can anyone tell me what I am doing wrong?
(I have commented out the attempt to read the ArrayList, as I cannot even create the file. Just trying the basic file creation.)
(Also, I have tried the code with "Shares.dat" instead of just "Shares" as filename, that didn't work either. I don't even know whether Android recognises .dat files and to be honest I am not 100% sure that is the file I need.)
(If by any chance anyone can help, I may not be able to test any solution until next weekend......)
As for the last but one line, originally it read 'context.getFileDir()' but my class extends ActionBarActivity and I found on internet a suggestion to change to this.getFileDir(). I got a null pointer warning when I used context.getFileDir()
file = new File("Shares");
if (file.exists()){
url.setText("File Exists");
/*try{
is = openFileInput("Shares");
oi = new ObjectInputStream(is);
details = (ArrayList<Action>)oi.readObject();//warning
oi.close();//need finally??
}
catch(Exception e){url.setText((e.getMessage()));}
url.setText(details.get(0).getAddresse());*/
}
else
{
try
{
**file = new File(this.getFilesDir(), "Shares");**
}
catch(Exception e){url.setText((e.getMessage()));}
}
If you want a reference to a file that's created in private storage, you'd want to use getFileStreamPath("shares.dat") instead of creating a new File object. File extension shouldn't matter, but it's a good practice to add a file extension to keep track for yourself what those files are for.
For example:
private boolean fileExists(Context _context, String _filename) {
File temp = _context.getFileStreamPath(_filename);
if(temp == null || !temp.exists()) {
return false;
}
return true;
}
Then, if you wanted to write to a file named "shares.dat" then you'd use openFileOutput("shares.dat", Context.MODE_PRIVATE). If you wanted to read in from that file, you'd use openFileInput("shares.dat").
// Read in from file
if(fileExists(this, "shares.dat")) {
FileInputStream fis = this.openFileInput("shares.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
ArrayList<Action> actions = (ArrayList<Action>)ois.readObject();
ois.close();
}
// Write out to file
FileOutputStream fos = this.openFileOutput("shares.dat", Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(actions);
oos.close();
All stream operations shown above have the ability to throw an IOException, so be sure to wrap that code in a try/catch block as needed.

How can I load a class from a jar file packaged in my .apk file?

I am trying to load a plugin implementation of an interface from a jar file which is in the /assets directory of my .apk file. The only way I've been able to get this to work is by extracting the jar file to private external storage and then passing that file to the DexClassLoader.
That works, but why should the jar have to exist in two places (the .apk and private external storage)? The DexClassLoader has to have a file path as its argument.
Is there a way to give it a direct path to the file that is in the /assets folder so that I don't have to use up external storage for an extra copy of what's already present?
Here are the relevant code snippets:
// somewhere in my main Activity ...
final File aExtractedDexFile = new File(getDir("dex", Context.MODE_PRIVATE),
LIBRARY_DEX_JAR);
extractDexTo(aExtractedDexFile);
loadLibraryProvider(aExtractedDexFile);
and
/** Extract the jar file that contains the implementation class.dex and place in private storage */
private void extractDexTo(File tJarInternalStoragePath) {
BufferedInputStream aJarInputStream = null;
OutputStream aDexOutputStream = null;
try {
aJarInputStream = new BufferedInputStream(getAssets().open(LIBRARY_DEX_JAR));
aJarOutputStream = new BufferedOutputStream(new FileOutputStream(tJarInternalStoragePath));
byte[] buf = new byte[BUF_SIZE];
int len;
while ((len = aJarInputStream.read(buf, 0, BUF_SIZE)) > 0)
{
aJarOutputStream.write(buf, 0, len);
}
aJarOutputStream.close();
aJarInputStream.close();
} catch (IOException e) {
if (aDexOutputStream != null) {
try {
aJarOutputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
if (aJarInputStream != null) {
try {
aJarInputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
and
/** Use DexClassLoader to load the classes from LibraryProvider */
private void loadLibraryProvider(File tFile) {
// Internal storage where the DexClassLoader writes the optimized dex file to.
final File aOptimizedDexOutputPath = getDir("outdex", Context.MODE_PRIVATE);
// Initialize the class loader with the secondary dex file.
DexClassLoader cl = new DexClassLoader(tFile.getAbsolutePath(),
aOptimizedDexOutputPath.getAbsolutePath(),
null,
getClassLoader());
Class<?> aLibProviderClazz = null;
try {
// Load the library class from the class loader.
aLibProviderClazz = cl.loadClass(LIBRARY_PROVIDER_CLASS);
sLibraryProvider = (LibraryInterface) aLibProviderClazz.newInstance();
} catch (Exception exception) {
// Handle exception gracefully here.
exception.printStackTrace();
}
}
Is there a way to give it a direct path to the file that is in the /assets folder so that I don't have to use up external storage for an extra copy of what's already present?
The answer is No. I suppose you follow this blog posted by official source implementing your code. if there is a better way of doing things, the bloger should recommend it in his blog.
Reason why you need optimizedDirectory is explained in the API:
This class loader requires an application-private, writable directory to cache optimized classes.
Also note that assets directory is not writable in apk, so it can't be done with purely assets directory.
Reason why you need copy jar file is a little bit subtle, mentioned in the blog:
First, it has to be copied to a storage location whose path can be supplied to the class loader.
Everything (folders/files) embedded within apk archive is not exposable (or interpretable) to the underlying file system at runtime. In another word, dexPath required in both DexClassLoader and PathClassLoader's constructor need a solid path string like /data/data/com.example/dex/common-lib.jar that represents the file in file system.

How to get access to raw resources that I put in res folder?

In J2ME, I've do this like that:
getClass().getResourceAsStream("/raw_resources.dat");
But in android, I always get null on this, why?
For raw files, you should consider creating a raw folder inside res directory and then call getResources().openRawResource(resourceName) from your activity.
InputStream raw = context.getAssets().open("filename.ext");
Reader is = new BufferedReader(new InputStreamReader(raw, "UTF8"));
In some situations we have to get image from drawable or raw folder using image name instead if generated id
// Image View Object
mIv = (ImageView) findViewById(R.id.xidIma);
// create context Object for to Fetch image from resourse
Context mContext=getApplicationContext();
// getResources().getIdentifier("image_name","res_folder_name", package_name);
// find out below example
int i = mContext.getResources().getIdentifier("ic_launcher","raw", mContext.getPackageName());
// now we will get contsant id for that image
mIv.setBackgroundResource(i);
Android access to raw resources
An advance approach is using Kotlin Extension function
fun Context.getRawInput(#RawRes resourceId: Int): InputStream {
return resources.openRawResource(resourceId)
}
One more interesting thing is extension function use that is defined in Closeable scope
For example you can work with input stream in elegant way without handling Exceptions and memory managing
fun Context.readRaw(#RawRes resourceId: Int): String {
return resources.openRawResource(resourceId).bufferedReader(Charsets.UTF_8).use { it.readText() }
}
TextView txtvw = (TextView)findViewById(R.id.TextView01);
txtvw.setText(readTxt());
private String readTxt()
{
InputStream raw = getResources().openRawResource(R.raw.hello);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i;
try
{
i = raw.read();
while (i != -1)
{
byteArrayOutputStream.write(i);
i = raw.read();
}
raw.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return byteArrayOutputStream.toString();
}
TextView01:: txtview in linearlayout
hello:: .txt file in res/raw folder (u can access ny othr folder as wel)
Ist 2 lines are 2 written in onCreate() method
rest is to be written in class extending Activity!!
getClass().getResourcesAsStream() works fine on Android. Just make sure the file you are trying to open is correctly embedded in your APK (open the APK as ZIP).
Normally on Android you put such files in the assets directory. So if you put the raw_resources.dat in the assets subdirectory of your project, it will end up in the assets directory in the APK and you can use:
getClass().getResourcesAsStream("/assets/raw_resources.dat");
It is also possible to customize the build process so that the file doesn't land in the assets directory in the APK.
InputStream in = getResources().openRawResource(resourceName);
This will work correctly. Before that you have to create the xml file / text file in raw resource. Then it will be accessible.
Edit Some times com.andriod.R will be imported if there is any error in layout file or image names. So You have to import package correctly, then only the raw file will be accessible.
This worked for for me: getResources().openRawResource(R.raw.certificate)

Categories

Resources