regarding the Android Assets manager, is it possible to get a file from the assets without context? I read that I can initialize a File object with "file:///android_assets" kind of path, and then get the file from there, but it says that the file does not exist (Honeycomb).
What is the general workaround around this issue? There is no any way to get the context on the place I need the files from the assets.
Thanks
To get access to the Context where it's not present you can extend Application class and create the static reference to the Context. This way you can access it from anywhere within the application:
public class MyApp extends Application {
public static Context context;
#Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
}
Related
I've been wondering about something in android development.
I have a class for requesting permissions to the device in an easier way for me, this class name is PermissionRequester
public class PermissionRequester{
int sdk;
Context context;
public PermissionRequester(Context context) {
this.context = context;
sdk = Build.VERSION.SDK_INT;
}
}
In a beginning, I was requesting a Context in my constructor for checking if the permission was allowed or denied by the user. Using Context didn't work, so I change "Context" to "Activity" and it worked.
public class PermissionRequester {
int sdk;
Activity activity;
public PermissionRequester(Activity activity) {
this.activity = activity;
sdk = Build.VERSION.SDK_INT;
}
}
In my MainActivity, I instanciate like this
PermissionRequester requester = new PermissionRequester(MainActivity.this);
So my question is the next:
Why didn't I get a compile error in both cases using Context and Activity?
Context is the Base Object. To be more precise an Activity is a specialization of Context. That's why you Activity works in your case.
Take a look at this architecture of an Activity:
java.lang.Object
↳ android.content.Context
↳ android.content.ContextWrapper
↳ android.view.ContextThemeWrapper
↳ android.app.Activity
Add to DEX7RA's answer.
Another important Context is Appication, which is base class for those who need to maintain global application state. You can provide your own implementation by specifying its name in your AndroidManifest.xml's tag, which will cause that class to be instantiated for you when the process for your application/package is created.
I usually do application wide initialization in Application's OnCreate event, like creating database, log file, etc.
there is Class Named "Configs.java" contains :
public Contect context;
public Activity currentActivity;
On Global Class Named "App.java" :
public static Configs configs = new Configs();
On Main Activity Java Class Oncreate :
App.configs.context = getApplicationContext();
App.configs.currentActivity = this;
On Products Activity Java Class Oncreate (Main Activity Not Finished And Must Work In Background):
App.configs.currentActivity = this;
After Long Time Minimized , it shows An Error On Bellow Line From Products Activity Java Class :
App.configs.currentActivity = this;
NullPointerException
Unable To Use "Bundle savedInstanceState" Because It's Activity Valiable
Try moving this code to onResume() instead of onCreate() and see if the error still exists.
Using static variables on Android is no good. This post explains that Android is very likely to kill your app (kills your Application instance, hence the static variable becomes null when your app is recreated and the class loader reinstantiates your vars) to save memory. The post also refers to Saving Activity state in Android which offers an alternative to save stuff with Bundles.
Anyway, if you need a quick solution, make your Configs class a singleton, and use getters and setters instead of making it public. Make the getter check if your singleton is null, and in this case, instantiate a new and return it. You won't get NPEs but it is very risky since it won't restore the previous state.
I am trying to open a file which is in the assets folder. But using getAssets() gives the error given above. I know I have to pass the context from another activity, but I can't do that either as then another error comes-"The method onCreate(SQLiteDatabase, Context) of type ClassName must override or implement a supertype method". So I am stuck. Is there a better way of opening that file? Here is the line:
InputStream is = getAssets().open("file1.txt");
*Note: ClassName is not an activity, it's just a class, so getAssets() cannot work without passing context from another activity.
Edit: Here is the class and onCreate declaration:
public class DatabaseHandler extends SQLiteOpenHelper {
#Override
public void onCreate(SQLiteDatabase db) {//some stuff
InputStream is = getAssets().open("file1.txt");
//more stuff
}
}
I am trying to open a file which is in the assets folder. But using getAssets() gives the error given above.
getAssets() is a method on Context.
I know I have to pass the context from another activity, but I can't do that either as then another error comes-"The method onCreate(SQLiteDatabase, Context) of type ClassName must override or implement a supertype method".
Since you declined to paste the source code where this is occurring, it is difficult to help you.
ClassName is not an activity, it's just a class
More specifically, it is a subclass of SQLiteOpenHelper.
so getAssets() cannot work without passing context from another activity.
A SQLiteOpenHelper gets passed a Context to its constructor, which you need to override.
Beyond all of this, if your objective is to package a database with your app, please use SQLiteAssetHelper, as it has solved this problem.
How about:
InputStream is = getActivity().getAssets().open("file1.txt");
Use getContext() Method. Set getContext().getAssets(). I hope it will works .Actually getAssets() is a method on Context .
For more details you can visit Here
I have found one answer that appears to say I should create a separate class and make a static MyApplication object and make a get method. Then any class can call MyApplication.get() to retrieve the context.
Is there any other cleaner way? This is my situation:
I have a class A and a class B. Class A contains an object from class B (let's call the object b). In class A I call, "b.play()". However, I get a null pointer exception because class B needs to pass a context to the MediaPlayer.create() method.
Until now I threw together a hack and from class A I called.... "b.play(this)" and simply passed the context to B. However that is pretty ugly and looks like a bad use of OOP.
Any thoughts?
This problem seem to arise a lot in Android development. One solution to obtaining a reference to a specific Context is subclassing the Application and grab a reference to the Context which you want.
public class MyApplication extends Application {
private Context context;
#Override
public onCreate() {
super.onCreate();
this.context = getApplicationContext() // Grab the Context you want.
}
public static Context getApplicationContext() { return this.context; }
}
This solution however requires that you specify the name of your subclass in your manifest.
<application
android:name=".MyApplication"
</application>
You can then use this anywhere in your application like this in non-activity classes.
MyApplication.getContext(); // Do something with the context! :)
If class B requires a Context to operate, then I don't see any problem having class A provide that to it (through a parameter on the play method, a parameter in a constructor, etc).
I don't think you are doing any poor OOP by providing class B the dependencies that it needs to do it's job.
Passing this around is a viable way of doing things, especially if this is the activity that creates the object in need of a Context. Sometimes, I'll put the Context into the constructor (like public MyObject(Context context){this.context = context;}), so that you don't need to send it every time. However, if your object is shared across multiple Activities, you should probably update the context it is looking at with the new Activity, though I haven't tested what happens if you use the old activity.
I've answered also here.
You can do that using ContextWrapper, as described here.
For example:
public class MyContextWrapper extends ContextWrapper {
public MyContextWrapper(Context base) {
super(base);
}
public void someMethod() {
// MediaPlayer.create(this, ...)
}
}
I'm trying to put configuration, such as URLs/etc, into a resource folder for a utility class to use. However, I don't want to pass the Context from the activities everywhere. I would like to be able to access a resource via a path name (seems like assets/ was designed for this use), without using a context to access the resource.
In this particular case, I want a singleton to use something in configuration when it's instantiated. It has no need for anything from resources besides that one time during instantiation. Therefore, having to pass in a Context every time getInstance() is called would be a complete waste.
Also, this is specific to the App's configuration, and should not be in stored in a shared system file or anything like that.
Use
Resources.getSystem().getString(android.R.string.someuniversalstuff)
You can use it ABSOLUTELY EVERYWHERE in your application, even in static constants declaration! But for system resources only.
For local resources use that solution.
You could extend the main application class and provide universal helpers there to access resources. This relieves the need for context as the application would provide the context instead of the caller. The application class is singleton style and should always be available while any portion of your application is running (including services).
public class MyApplication extends Application {
protected static MyApplication instance;
#Override
public void onCreate() {
super.onCreate();
instance = this;
}
public static Resources getResources() {
return instance.getResources();
}
}
This provides you access to:
MyApplication.getResources()....
Be sure to declare your custom application in your manifest to gain access to this. Assuming your custom application is in the root of your application's namespace:
<application
android:name=".MyApplication"
... >
I would recommend doing the following:
Rather than passing context everywhere make your activity class a singleton class with a public function that returns the context:
private static ActivityMain instance;
Initialize inside onCreate() before super.onCreate():
instance = this;
Then add these public functions to your activity:
/** Get singleton instance of activity **/
public static ActivityMain getInstance() {
return instance;
}
/** Returns context of this activity **/
public static Context getContext(){
return instance.getApplicationContext();
}
Now you can use the following anywhere in any class:
Context context = AntiMorphActivity.getContext();
String packageName = context.getPackageName();
int id = context.getResources().getIdentifier("web_page", "raw", packageName);
Unfortunately I don't think there is a real way around this. I lay mine out something like this, and also pass in the getApplicationContext() instead of the activity context.
public static AppController getAppController(Context context){
if(self == null) {
//Create instance
self = new AppController();
}
return self;
}
And then:
appController = AppController.getAppController(getApplicationContext());
The stackoverflow answer to the question below shows how to use POJO to obtain a stream to a resource, if you supply its path. This might be useful in cases you need to select a specific resource from one of many.
Is it possible to read a raw text file without Context reference in an Android library project