I have looked everywhere for an answer and every time I see someone else use the method:
getFilesDir();
But when I try and use that method in any way, especially:
File myFile = new File (getFilesDir();, filename );
Eclipse just says, "Cannot make static reference to non-static method getFilesDir from tye ContextWrapper"
I am trying to use it to get the internal directory to write a file for my application.
Thanks!
That is because in the static method you have not got the object of the class and getFilesDir is not a static method that means it will only be accessible via the object of class Context.
So what you can do is store the reference to the object in a static variable of your class and then use that in your static method.
for example:
static YourContextClass obj;
static void method(){
File myFile = new File (obj.getFilesDir(), filename );
}
also you will have to store the reference to the object in your onCreateMethod()
obj = this;
The best way to achieve this is
static void method(YourContextClass obj){
File myFile = new File (obj.getFilesDir(), filename );
}
I'm gonna talk about what happened to me. I'm developing a log system files, so i created a new class and i wanted to was for all my application and having many instances of this class doing different logs. So i thougth to create protected or public objects of my class on the application class that is similar to a singleton class.
So i had something like that:
public class MyApp extends Application {
protected LogApp logApp = new LogApp(getFilesDir());
When i called it from my main class to get the list files for example:
public class LogApp {
public File dirFiles;
//file parameter can't be null, the app will crash
public LogApp(File file){
dirFiles = file;
}
public File[] getListFiles(){
return dirFiles.listFiles()
}
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
MyApp myApp = (MyApp)getApplicationContext();
File file[] = myApp.logApp.getListFiles();
}
This was getting me an nullPointException error.
The solution in this case was so easy that i felt stuoid and proud at the same time.
I couldn't call to getFilesDir in MyApp's declaration space because at that moment there isn'r a context to get that Dir. The order of execute in an Android App is: Application --> Activity. Like it's said in Manifest file.
Solution? Create my object in onCreate event of my MyApp Class, it looks like this:
public class MyApp extends Application {
protected LogApp logApp;
void onCreate(){
logApp = new LogApp(getFilesDir());
So now i can use it in my main class in the same way i did it because exist an instance of my MainActivity that extends in last instance from Context Class.
Maybe i'm wrong with may explanation and this is not what is really happening in meanings of terminology and how works android. If someone understand better than me why this works i invite you to clear up our doubts.
I hope this will help you.
Related
I have a non visual class that need to read some files from the assets folder.
Is totally out-of-band so don't have a activity. How I can refer to it without pass down the activity?
Also I can accept a alternative to the assets way to put files (like .sql) to be read later on the android devices.
P.D:
This is a sample of the code where is called:
//Load asset not belong to anyone. Is that radical
let loadAsset(path:string) =
#if __ANDROID__
let sr = new StreamReader(?????.Assets.Open(path.Substring(1)))
seq {
while not sr.EndOfStream do
yield sr.ReadLine ()
}
#else
File.ReadLines(path)
#endif
What you really need is a Context. If you application has an Application class, you can use its Context to retrieve asset resources.
It should look something like this:
public class App extends Application {
public static Context context;
#Override public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
}
You can then used App.context to get resources/assets.
How to get an android asset without an Activity
Try using the following code:
let sr = new StreamReader(Android.App.Application.Context.Assets.Open(path.Substring(1)))
Hi I am kind of new to android, still learning. And my problem is that, for example I have a method which was created in the MainActivity and I need to call it from another class.
Is it a good practice to get the instance of the MainActivity so that I may be able to call the method in the MainActivity from another class?
This is an example:
public class MainActivity extends AppCompatActivity {
private static MainActivity inst;
public static MainActivity instances()
{
return inst;
}
#Override
public void onStart() {
super.onStart();
inst = this;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void showToast (String text){
Toast.makeText(inst, text, Toast.LENGTH_SHORT).show();
}
Then this is the other class:
public class broadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
MainActivity instance = new MainActivity();
instance.showToast(AnyText);
}
}
I saw this type of coding while looking at tutorials and wondered if it's a good practice or maybe there might be a better way? Since I get the warning of Do not place Android Context Classes in static classes
Thanks in advance for any insight or help! :D
I guess You want to make A singleton of Activity Class
but as Mention in All Pattern Design
using Singleton
If and Only If its only way to Make A Global Variable
Singleton is based on Lazing Initialing and Load On Memory
so I guess If you cant to Interact With Activiy You can Use
BroadCast Or Intents
You can call method from another class like this:
MainActivity instance = new MainActivity();
String data = instance.data();
and create data method in that class:
public String data() {
return mangaId;
}
Is it a good practice to get the instance of the MainActivity so that
I may be able to call the method in the MainActivity from another
class?
You totally can do this but you don't need to make it static and use a constructor. Just create a new instance like follows and you'll access the public methods
MainActivity mainActivity = new MainActivity();
mainActivity.showToast(text);
About the warning
It suggests avoiding having context fields defined as static. The warning itself explains why: It's a memory leak. If you make it static it will be accessible anywhere in your app and some methods can hold the reference to this context for a really long time and it won't be garbage collected. It will lead to a outofmemory exception and the app could crash. But here you're trying to invoke showToast() from broadcastreceiver so you can just get rid of static references. And it you need them in the future you safe ways to inject context
You cannot create instances of an Activity using the new operator.
You have to use an Intent to let an Activity to be created.
So you cannot get a reference to an instance of your activity.
The only methods you can use of your activity class are static ones.
I am looking for information regarding writing my own application class. In many tutorials on the net I have seen the following code:
class myapp extends Application
{
private static myapp mm;
private Context context;
public Context getContext()
{
return getApplicationContext();
}
public myapp getmyapp()
{
if(mm == null)
mm = new myapp();
return mm;
}
}
What is the difference in getting object of myapp and getApplicationContext and where to use object of myapp and where to use context object. I just want to clear the concept of usage of these objects.
that code is completely wrong:
public myapp getmyapp()
{
if(mm==null)
mm=new myapp();
return mm;
}
only the Android framework can instantiate the Application object. I mean, you can call new but the object won't be "connected" to the underlying framework
To have a static reference of the application object you should do as follows:
class MyApp extends Application{
// I fixed the names to follow some Java convention
private static MyApp instance;
#Override
public void onCreate() {
super.onCreate();
instance = this;
}
public static MyApp getMyApp(){
return instance;
}
Regarding the context, the code is not wrong, but simply doesn't make any sense. That's because the Application object already is the application context. So there's not need to ask for it.
Context is what gives Android apps access to resources, file system specific folders, permissions, etc (what I said about the Android framework creates it). The Application is one class that extends Context, other examples are Activity and Service classes.
I hope it's a bit clearer.
I'm a noobie in OOP and Android, I'm facing a little problem that is frustrating me so much.
I'm creating an app that uses permanent storage.
Initially I created the code that access the saved preferences all mixed into the MainActivity, that worked, then I wanted to move that code to a separated class file.
The problem is that for some reason it won't work in a separated class file and after trying and trying I found that I could create an inner class inside the MainActivity class and that way it works.
I believe that it is related to the fact that if I create it as an inner class I don't need to make the inner class to extend Activity (again).
When creating an external class for the permanent storage handling, I needed to extend Activity on that class and I think that is the problem but I'm not sure.
Can somebody please explain to me why this is happening and maybe suggest the correct approach?
following I'm including a code snippet that works, but my goal is being able to create the class PermanentStorageHelper in a separated class file.
Thanks in advance!
public class MainActivity extends Activity {
public static MainActivity _mainActivity;
private TextView textView1;
// OnCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Persistent preferences
PermanentStorageHelper ps = new PermanentStorageHelper();
// UI Initialization
textView1 = (TextView) findViewById(R.id.textView1);
String uId = ps.getuId();
UiHelper.displayOnTextView(this, R.id.textView1, uId);
}
// =============================================
// This is the class I'm talking about, I'm unable to move this to
// a separated class (.java) file.
// It seems to be related to the fact that, if making this a separated
// class file, I need to extend Activity again and that is what
// seems to be the problem
// =============================================
public class PermanentStorageHelper /*extends Activity*/{
// CONSTANTS
public static final String USERUNIQUEID="userUniqueID"; // Saved setting 1
public static final String FILENAME="mtcPreferences"; // Filename for persisting storage file
// Fields
public SharedPreferences shp; // SharedPreferences field (1)
public String uId;
public PermanentStorageHelper(){
// Preferences initialization (2)
shp = getSharedPreferences(FILENAME, MODE_PRIVATE);
// Read Preferences (3)
uId = shp.getString(USERUNIQUEID, null);
}
// Getters and Setters
public String getuId() {
return uId;
}
public void setuId(String uId) {
this.uId = uId;
}
}
pass a context to your new class:
public PermanentStorageHelper(Context context){
// Preferences initialization (2)
shp = context.getSharedPreferences(FILENAME, MODE_PRIVATE);
}
Then you can create your class like:
new PermanentStorageHelper(MainActivity.this)
for getSharedPreferences you need to have access to the activity or applicationContext
You can add context to your constructor and use it to call getSharedPreferences:
public PermanentStorageHelper(Context context){
// Preferences initialization (2)
shp = context.getSharedPreferences(FILENAME, MODE_PRIVATE);
// Read Preferences (3)
uId = shp.getString(USERUNIQUEID, null);
}
in which case you would need to pass it on when creating the instance of the object:
PermanentStorageHelper ps = new PermanentStorageHelper(getApplicationContext());
or
PermanentStorageHelper ps = new PermanentStorageHelper(MainActivity.this);
For every Activity I add to my app I'm noticing a lot of similar code being used in the initialization of the Activity. A helper class with a static method to wrap this similar code seems the way to go.
I first thought of a singleton class. I could add static methods/variables and use them across the application. I haven't really tried to see how would this work in an Android application. Searching a little bit more I saw something about creating a class extending Application. For this I did a simple test:
public class MyApp extends Application {
public static String DEMOTEXT = "WORKING!";
public static void ShowToast(Context context, String text) {
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
}
MyApp.ShowToast(this, MyApp.DEMOTEXT); // Placed on onCreate of some Activity
This works exactly as I expected. Is this the way to go on Android or is there a better convention? Anything else I should consider when doing this?
By the way, should I use the final keyword on the string? What about the method?
EDIT: I just read this:
There is normally no need to subclass Application. In most situation,
static singletons can provide the same functionality in a more modular
way. If your singleton needs a global context (for example to register
broadcast receivers), the function to retrieve it can be given a
Context which internally uses Context.getApplicationContext() when
first constructing the singleton.
http://developer.android.com/reference/android/app/Application.html
Should I use a singleton then?
Application is primarily used for a global application initialization. You would create your own class, override Application.onCreate() and initialize your static application data there.
Dont forget to declare it in the AndroidMainfest.xml:
<application
android:icon="#drawable/icon"
android:label="#string/app_name"
android:name="your.package.path.to.MyApp">
A static helper class is made the way you did.
The convention is to use lower case letter at first position, so MyApp.showToast(...).
You would use final for the String if you would want to avoid madifications on other places (since it should be a contant).
// this would allow ...
public static String DEMOTEXT = "WORKING!";
// ... to do this somewhere else
MyApp.DEMOTEXT = "NOT WORKING!"
I haven't tried this but I think you should be able to do something like this as well.
public class MyActivity extends Activity {
private static final String DEMOTEXT = "WORKING!";
#Override
public void onCreate(Bundle bundle)
{
super.onCreate(bundle);
Toast.makeText(this, DEMOTEXT, Toast.LENGTH_SHORT).show();
}
}
Now for all activities that need to use that initialization could just extend your base activity class.
public class SomeActivity extends MyActivity {
...
// Should display the toast on create
...
}
Yes just use a singleton. Well in this case if your methods are static, you don't even need a singleton. Just a class with static methods.