I am trying to get id of an image by using following code.
public class MovieActivity extends ActionBarActivity {
private Context con;
String name = "test";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
con = MovieActivity.this;
setContentView(R.layout.activity_movie);
}
public void updateScreen(){
int imageResource = con.getResources().getIdentifier("drawable/" + name , null, con.getPackageName());
}
}
When I run it, I get exception:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
I thought the problem was Context so I added con variable which gets context when code runs. I made some researches and tried another methods but I got same exception every time. Can anyone help me?
EDIT: When I use the same code line in MainActivity, it works perfectly. But in another class, it fails.
public class SomeMovie extends MovieActivity { }
public class MainActivity extends ActionBarActivity {
protected void onCreate(Bundle savedInstanceState) {
SomeMovie movie = new SomeMovie();
movie.updateScreen();
}
}
SomeMovie class is child of MovieActivity class. I call the method on that. I debugged the code and noticed that Context is null when code gets into updateScreen() method. Is it wrong to use inheritance on activity classes?
Change
int imageResource = con.getResources().getIdentifier("drawable/" + name , null, con.getPackageName());
to
int imageResource = getResources().getIdentifier("drawable/" + name , null, con.getPackageName());
You are already in an Activity's context, so use it. (No need to use the this keyword to refer to it)
EDIT:
You are not defining a layout for the SomeMovie Activity, so its context is always null.
You have to define the activity's layout in its onCreate method :
public class SomeMovie extends MovieActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.somemoviexml);
...
}
}
Related
I'm trying to make some utils functions to use in a bigger app later(download file from url, upload file to url etc)
So in MainActivity I have only 2 buttons that on click call static methods from Utils class.
However, I want on MainActivity to have some indicators of how things working on download/upload methods(connecting, connection success/fail, percent of download etc) so I put on MainActivity a TextView that will show that. I made an interface ICallback that contains void setConnectionStatus(String status) and from Utils class I use this to send to MainActivity the status.
Here are some parts of the code :
public class MainActivity extends AppCompatActivity implements ICallback {
Button btnDownloadDB, btnUploadDB, btnUploadPics;
TextView txtStatus;
ProgressBar pb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Initialize stuffs
initViews();
//Setting listeners
btnDownloadDB.setOnClickListener(v -> {
txtStatus.setText(R.string.connecting);
pb.setVisibility(View.VISIBLE);
Utils.downloadFile(DOWNLOAD_DB, DB_FILE_NAME);
});
}
#Override
public void setConnectionStatus(String status) {
Log.d("MIHAI", status);
txtStatus.setText(status);
}
The interface :
public interface ICallback {
void setConnectionStatus(String status); }
And the Utils class :
public class Utils {
static ICallback callback= new MainActivity();
public static void downloadFile(String downloadURL, String fileName) {
IFileTransferClient client = ServiceGenerator.createService(IFileTransferClient.class);
Call<ResponseBody> responseBodyCall = client.downloadFile(downloadURL);
responseBodyCall.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d("MIHAI", "connection ok");
callback.setConnectionStatus("Connection successful");
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("MIHAI", "err...fail");
callback.setConnectionStatus("Connection failed. Check internet connection.");
}
});
}
The problem appear on MainActivity, when I try to set text of the txtStatus TextView getting a null reference error even if the txtStatus is initialized on initViews() method.
The Logs are working fine so I get the right status in MainActivity. I tried to initialize the TextView again in that function before seting the text and im getting : "java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:183)"
Is there any chance to make this work?
Thank you for reading.
Kind regards,
Mihai
There are multiple problems with your solution but the main one is this line:
static ICallback callback= new MainActivity();
First of all, never hold a static reference to Activity, Fragment, Context or any Context related classes. These classes are either bound to a Context or represent the Context itself. You may leak memory this way. But that is the other problem.
What is the actual problem in your code is that new MainActivity() in Utils class creates an absolutely different instance of MainActivity that has nothing to do with MainActivity that is responsible for displaying your UI in the runtime.
What you should do instead is pass an instance of ICallback to the function as an argument:
public static void downloadFile(String downloadURL, String fileName, ICallback callback) {
...
}
And remove static ICallback callback= new MainActivity();.
Note: when you pass a callback object to a function make sure when it is called your Activity is not in a finished state.
I have an activity and a fragment working with.
In the activity, i'm initializing the current user like this(manually):
User currentUser;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
currentUser = new User("email", "name", "secondName", "age");
\\.....}
the MainActivity contains a method like this :
public User getCurrentUser() {
return currentUser;
}
now, here is the problem :
in the child fragment i'm calling getCurrentUser from mainActivity like this :
User u = MainActivity.newInstance().getCurrentUser();
MainActivity.newInstance() - defined in mainActivity like this, returning a static instance of activity :
private static MainActivity mainActivityInstance = new MainActivity();
public static MainActivity newInstance() {
return mainActivityInstance;
}
the problem is that getCurrentUser returns a null object reference even though currentUser is initialized in mainActivity with valid data.
So, calling for example
u.getName();
will throw me a NullPointerException
How can i solve this? i feel like i'm freaking out
Thanks.
MainActivity.newInstance() - defined in mainActivity like this, returning a static instance of activity :
Never create an instance of an activity directly yourself.
the problem is that getCurrentUser returns a null object reference even though currentUser is initialized in mainActivity with valid data
Those activity instances are separate Java objects.
From a fragment, call getActivity() to retrieve the activity object that is hosting the fragment. This is covered in any good book or course on Android app development.
As many people said: "You can't instantiate an Activity in a Fragment".
Second: there are many options you can implement in order to get the User in a Fragment. Here are the common options:
1 - Pass the user as a parameter in the fragment:
public static FragmentChild newInstance(User user){
Bundle b = new Bundle();
b.putSerializable("USER_PARAM",user);
FragmentChild fragment = new FragmentChild();
fragment.putArguments(b);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
User user = getArguments().getSerializable("USER_PARAM")
}
public class User implements Serializable {}
2 - Use the method ((MainActivity)getActivity()).getCurrentUser(). It will work but if you want to do it in the right way you should use an interface instead of using the MainActivity directly.
Interface option:
public class MainActivity extends AppCompatActivity implements UserDeliver {
#Override
public User getUser(){
return user;
}
}
public class MyFragment extends Fragment {
private UserDeliver userDeliver;
private User user;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
user = userDeliver.getUser();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
userDeliver = (UserDeliver) context;
}
#Override
public void onDetach() {
super.onDetach();
userDeliver = null;
}
public interface UserDeliver {
User getUser();
}
}
First off- you can't create an Activity via new. It will compile, but not be properly initialized because only the framework can do that.
Secondly- never hold an activity in a static variable. This will leak memory. Lots of memory, because the entire view hierarchy has a reference from the Activity. You will cause OOM errors doing this.
U are generating a newInstance of the MainActivity everytime you do MainActivity.newInstance()
Try to retrieve your user with ((MainActivity)getActivity).getCurrentUser();
Or create the instance of your user in the fragment
Here is the parent class:
public class void ParentClass () extends Activity {
private ListView _listView;
#Override
protected onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_parent);
_listView = (ListView) getViewById(R.id.list_view);
ChildClass cc = new ChildClass();
}
protected void SetScroll() {
try {
_listView.setFastScrollEnabled(false);
} catch (Exception e) {
e.printStackTrace();
}
}
Here is the child class:
private void ChildClass extends ParentClass () {
public ChildClass() {
SetScroll();
}
}
Forgive me with regards to the syntax as I'm typing this from memory. The problem with these classes is that the SetScroll function called from the CallParent function does not work because it is unable to find the right _listView reference (it becomes null). What should I do to make it work correctly? Bear in mind that this is just an example.
But the view is getting null is because you are extending an activity class and before using its view you need to call the onCreate and set the view (if child activity needs new one). But for that you will have to follow the complete flow of the lifecycle. This will help you in extending an activity class. android how to create my own Activity and extend it?
Call parent class activity like this (Just for info). With your code it wont work. You need to correct your code first. See the link I have posted.
super.SetScroll();
I have a function in main.java that uses some UI elements like spinner to textview.
public void updateNearByPeople() {
reportEventPeopleAroundSpinner = (Spinner) findViewById(R.id.peopleAround);
…
}
When I call this function from within class, it works fine.
But when I call this function from another class2.java through an object findViewById throws java.lang.NullPointerException
If I make the function and all variables in it static than it also works fine while calling from class2.java but it doesn’t work with object calls.
How can I solve this and made of object aware of the context?
In main.java:
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_view);
mainAppContext = this;
Main mainObj=new Main();
gMapObj.initiateMap(mainAppContext,mainObj, mapFrag);
}
In class2.java:
public boolean initiateMap(Context appContext, Main mainObj, MapFragment mapFrag) {
mainAppContext = appContext;
mainAppObject = mainObj;
…
mainAppObject.updateNearByPeople();
}
Main mainObj=new Main();
you can't do that. The activity needs to go through its lifecycle, to build up its view hierarchy. If you just instantiate it through the new operator, neither its onAttach or onCreate method will be called. It means that you can not access resources and views as well
In my Android app, I want to use a single variable for the log name in multiple files. At the moment, I'm specifying it separately in each file, e.g.
public final String LOG_NAME = "LogName";
Log.d(LOG_NAME, "Logged output);
I've tried this:
public final String LOG_NAME = (String) getText(R.string.app_name_nospaces);
And while this works in generally most of my files, Eclipse complains about one of them:
The method getText(int) is undefined
for the type DatabaseManager
I've made sure I'm definitely importing android.content.Context in that file. If I tell it exactly where to find getText:
Multiple markers at this line
- Cannot make a static reference to the non-static method getText(int)
from the type Context
- The method getText(int) is undefined for the type DatabaseManager
I'm sure I've committed a glaringly obvious n00b error, but I just can't see it! Thanks for all help: if any other code snippets would help, let me know.
That's because getText is a method of Context. It does not matter if you import the Context class; what matters is that you invoke that method from a Context (for instance, the Activity class is a Context (it inherits Context)).
In that case, what I'd recommend, is creating a Application class that returns the context you want. Here I explain how to do it. After that you can do something like:
public final String LOG_NAME = (String) App.getContext().getText(R.string.app_name_nospaces);
Depending on what sort of 'files' you are using, you can define a TAG that is used.
For example, when I create an app, I like to create a base class for my Activity classes...
Suppose my app is called 'Wibble', and my package is com.mydomain.Wibble...I create my base Activity like so...
package com.mydomain.Wibble
public class WibbleActivity extends Activity {
final protected String TAG = this.getClass().getName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// I'll explain how this next line works later
android.util.Log.d(TAG, "Entered onCreate()...");
}
}
Now suppose I derive an activity as follows...
package com.mydomain.Wibble
public class SomeActivity extends WibbleActivity {
#Override
protexted void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Don't Log "Entered onCreate()..." - WibbleActivity does it for me
android.util.Log.d(TAG, "SomeText");
}
}
Then I derive another Activity...
package com.mydomain.Wibble
public class SomeOtherActivity extends WibbleActivity {
#Override
protexted void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Don't Log "Entered onCreate()..." - WibbleActivity does it for me
android.util.Log.d(TAG, "SomeOtherText");
}
When onCreate() is called for SomeActivity, the output will be...
com.mydomain.Wibble.SomeActivity Entered onCreate()...
com.mydomain.Wibble.SomeActivity SomeText
...when onCreate() is called for SomeOtherActivity however, the output will be...
com.mydomain.Wibble.SomeOtherActivity Entered onCreate()...
com.mydomain.Wibble.SomeOtherActivity SomeOtherText
Neither activity needs to know specifics through an explicit string and the package name is prefixed. Obviously it will only work in certain situations but I find it useful.