File Access of any kind in Android SDK - Android Application - android

File Access in Android SDK.
I am trying ( and have been for a while ) to find a way to access any files within my android application. By file i mean: Random Access, Input, Output, Shared, Private, whatever kind of file.
There are no working examples online ( other than what the android sdk site claims to work ), and any attempt to try examples on Android SDK or any other website fail.
Can someone please give sample code from beginning to end showing a class which uses files in their android application. something that can write data as simple as an integer ( i don't care what it writes )

Somehow I forgot that all example code from the Android examples has to be written in the Activity itself ( yes it does ).
In order to use the openFileInput method outside of the main Activity you must have a reference to the Activity Context which can be used in other classes with the import using:
import android.content.Context;
you must pass the Activity Context to another Context defined in that other class such as...
Context context;
public void passContext( Context cont ) {
context = cont;
}
and then you can use context from the new class ( which referes to the resources available to the main Activity ) to access files and other resources.
HaHa hope this help anyone else.

Related

Accessing assets of main application inside package

i'm currently trying to develop a package for a Flutter App, with Kotlin. My issue is that I need to provide the package with a config file, which should only be defined inside the main App. Since the config differs for the Dev and Prod environment, the app should pass through the path of the File via the Method Channel. The problem is that the package isn't able to access the assets folder of the calling application.
Path: "assets/config.json" (the root being the main application)
Steps I already tried:
Creating the file inside the res/raw & accessing the config file through a ressource id -> Kotlin gives me an "Unresolved reference" error, unless I create the file inside the packages res/raw
Instead of passing through the path, I tried passing through the content of the config & writing it into an empty temporary file. The code in Kotlin like this:
val config = File(applicationContext.filesDir,"config.json")
config.writeText(configContent)
-> This works, but it seems like a weird solution to the problem.
please let me know if I need to provide further information & thank you in advance!
edit:
The Java Method that is called during initialisation:
public static void createMultipleAccountPublicClientApplication(#NonNull final Context context,
#NonNull final File configFile,
#NonNull final IMultipleAccountApplicationCreatedListener listener)
Flutter assets aren't files - they are packaged up and only available through the rootBundle. So, if you want to make a file from a text asset, someone has to load the asset and write it to a file.
As your plugin user will be in charge of the asset, they will have to do the first part (and will end up with a String). The question arises of who should do the writing.
You could make the plugin user use path_provider to find the temporary directory and write it there and then pass you the file path. Eventually, down in the Java, you new File(theTempFilePath). Or they could pass the string to the Dart half of your plugin and you create the temp file in the same way.
It's probably more convenient if they pass your plugin the string, you pass that to the native side and have the native side create a temporary file and write the string there. (BTW, I assume we are talking about this config file: https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-configuration#how-to-use-a-configuration-file )
See this answer for creating temporary files: Creating temporary files in Android
Note that there's actually no reason that your plugin user then needs to use an asset. They could, instead, just hard code the string in their code if the configuration never really changes.
There's an argument that as this is a JSON configuration file, you may not want to bother your user with the details of this JSON configuration file. You may want to default it in your Dart code (why not hard code it as a string, as above, if it never really changes) and then provide some methods to override particular values like the client id and the redirect uri, which may be the only things that users ever change in practice. So rather than making them supply a complete JSON file, they just give you those two strings and you plonk them into your default JSON. Maybe a version 2 feature :)

Android/Java Standard Package names are they protected

I need to make a reference to a builtin Android Java Class in NDK c++ code.
You can do it by
cls_tm = (*env)->FindClass(env, "javax/crypto/Cipher");
I am worried someone can tamper with apk, extract the java code then create their own class with the package name javax.crypto.Cipher, and read all the sensitive data I am passing to it. I am new to Java and Android so I wanted to know if it is possible to create your own package with same name as built in packages like javax.crypto.Cipher?
It is possible to create classes with the same name. However, they do not take the place of existing classes.
Every class is loaded by a class loader. Class loaders form a hierarchy, with the "bootstrap" class loader at the very top. The class loader that loads your app's classes is created by the Android app framework; it is a child of the "system" class loader, which is a child of the bootstrap loader.
When your app references a class, it asks its class loader to find it by name. Each loader will either return a class that it defined, or ask its parent to find it. (The default behavior is to ask the parent first, but an individual loader can override this.)
javax.crypto.Cipher is part of core.jar, which is loaded by the bootstrap class loader. So unless your application's class loader decides to replace Cipher with its own version, you will get the system version.
(The JNI FindClass call is actually a bit strange. Depending on where you are when you call it, it can actually end up in the system class loader rather than your app's loader. See this section in JNI Tips for an explanation.)
Suppose you really did want to replace Cipher. You can provide your own version, and your app code will happily use it. However, when you try to pass it to some other code in core.jar, your app will fail. This is because classes loaded in the VM aren't unique by name, but rather by the combination of name and class loader. So you can't pass a Cipher+MyAppLoader into something that expects a Cipher+bootstrap.
In any event, if somebody modified your APK, they would have to re-sign it; since they don't have your private key, it wouldn't look like an app that came from you.
If somebody modified a device and replaced the system Cipher with their own version, they can do whatever they want.

context.getResources().openRawResource() crashes the app

I'm trying for a while to make android read from a text file that I already have in the R.raw folder.
I have the function void readfile(Context context) that contains the line
InputStream is = context.getResources().openRawResource(R.raw.data);
However when I try to run the app it crashes at that exact line. Can you tell me a workaround? Or another way to read from that file?
There is obviously a problem with the given context. You should post your logcat.
There is 2 ways to solve your problem.
Pass a correct context: see what is wrong with your program and why the given context is not correct.
Extend Application, and save the application context in a static variable: see this post

Why do filestreams need a context?

I've been working on developing a library for my company for the past couple months and have been annoyed by the fact that filestreams seem to need a context whenever I store or load data to the internal storage.
I have designed the library to work like this :
A singleton class is made for providing and handling a keychain(containing app key and device id) and authinfo(user and password)
Whenever a request to call to a web service is made the calling class will attempt to get an instance of the singleton class and get the keychain and auth info through it like such :
SingletonClass.getInstance().getCredentials(Context ctx);
The result of this is that I need to constantly provide the context of the calling activity as most of my library revolves around calling an API with credentials and device id as parameters.
I am specifically referring to these lines :
....
FileOutputStream fos = ctx.openFileOutput(filename,
Context.MODE_PRIVATE);
fos.write(buf);
fos.close();
....
I am confused as to why the specific context of the activity calling is needed. Any help is greatly appreciated. Is there another way of solving this design issue ?
The application context should work for this - you could consider using this method: Using Application context everywhere? so you can easily get the application context without having to pass it around.
The file storage API is provided by the Context class.
So you need it.

How can I initialize the Sender ID for Android C2DM without using a hard-coded value in a static variable?

I'm adding Android C2DM to a Android library project. I started with the com.google.android.c2dm package that is included with JumpNote and Chrome To Phone. In order to use this package, you have to subclass the C2DMBaseReceiver service which takes the Sender Id as an argument to it's constructor. In JumpNote, this argument is initialized using a hard-coded static variable in a config class. However, in an Android library project, which may be used by multiple concurrently running apps I don't think I can use a hard-coded static variable (that is, I believe it could lead to problems when/if multiple apps are trying to access/modify the static variable).
I tried to think of a way to initialize the Sender Id without using a static variable and am stumped so far.
The obvious solution would be to use the Manifest or a Resource string or a combination of the 2. For example, in strings.xml I might have a "ac2dmSender" string, which is accessed in a meta-data child of the C2DMReceiver service declaration in the manifest. However, it seems that you cannot get a reference to the PackageManager or ResourceManager from a static context, so there is no way for me to then retrieve the meta data in such a way as to pass it in to the constructor of C2DMBaseReceiver.
Please let me know that I'm missing something! Thanks in advance.
We had same problem.
We solved it by using properties file under the assets folder.
Can load the properties staticly by using static configuration helper class.
On the first time the application is loaded can get the properties file using the Application context.
for example:
1. init the static configuration
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myConfig = new WLConfig(getApplication());
}
Then use in the configuration class:
myProperties.load(context.getAssets().open("myclient.properties"));
And get the sender email:
return myProperties.getProperty(WL_C2DM_SENDER)
However, in an Android library project, which may be used by multiple concurrently running apps I don't think I can use a hard-coded static variable (that is, I believe it could lead to problems when/if multiple apps are trying to access/modify the static variable).
"Multiple concurrently running apps" each have their own copy of the static variable, since each runs in its own process.

Categories

Resources