I have a diagram as follows
Activity 1 --send data--> Service1
^
|
Open app--------------------
^
|
Activity 2------------------
It means the activity 1 will send the data to a Service 1. The service 1 is a running background service with return in onStartCommand() is START_STICKY. Currently, I am using putExtra() function to exchange the data. And in the service I will getExtra data as follows steps:
In Activity 1
Intent start_service = new Intent(getContext(), ConnectService.class);
start_service.putExtra("data", "123");
getContext().startService(start_service);
In onStartCommand() of Service 1
String data=null;
if(intent.hasExtra("data")){
Bundle bundle = intent.getExtras();
if(!bundle.getString("data").equals(null)){
data= bundle.getString("data");
}
}
else
data="0";
I used the hasExtra function to check whether data is set or not. In my purpose, the case 1 is that the Service 1 can receive data from the Activity 1 . In the case 2, if we do not start from the Activity 1, for example, when I clean all running app, the phone will be open the Service 1 automatically due to START_STICKY, the Service 1 will set data equal "0". Hence, my issue is from second case, the application is crash because it cannot check the Extra exist or not.
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Intent.hasExtra(java.lang.String)' on a null object reference
How could I fix the issue? Thank all
String data=null;
if(getIntent()!=null && getIntent().getExtras()!=null){
Bundle bundle = getIntent().getExtras();
if(!bundle.getString("data").equals(null)){
data= bundle.getString("data");
}
}
else
data="0";
try this,notice the change in if condition
At this step intent might be null. Also your code results in a possible null value for data. Instead you could do something like the following:
String data = null;
if (intent != null) {
data = intent.getStringExtra("data");
}
if (data == null) {
data = "0";
}
Also you should not use equals() to check for null values. Always use == null instead.
Related
I know there are plenty such questions here - but I believe my issue is unique.
I have a listview of modules, when a user selects a module another activity opens showing the 'decks' for that module. This requires the second activity to know which listview item was clicked. The following is how I try to achieve this.
modulesListView.setOnItemClickListener((parent, view, position, id) -> {
ModuleObject moduleObject = list.get(position);
Intent intent = new Intent(FlashCards.this, FlashCardDecks.class);
Bundle extras = new Bundle();
extras.putString("EXTRA_MODULE_ID", moduleObject.getModuleId());
extras.putString("EXTRA_MODULE_NAME", moduleObject.getModuleName());
intent.putExtras(extras);
startActivity(intent);
});
In the new activity I access moduleName and Id like so:
Bundle extras = getIntent().getExtras();
assert extras != null;
String moduleId = extras.getString("EXTRA_MODULE_ID");
String moduleName = extras.getString("EXTRA_MODULE_NAME");
I then use the moduleName to setTitle and moduleId to access firebase and fill a listview. All good. The variables are passed as they should be.
But in my second activity I have dialogs that let users add and remove 'decks' from the firebase database using the following reference...
decksDatabaseReference = firebaseDatabase.getReference().child(userID).child("decks").child(moduleId);
Using this reference - a user can add 'decks' to a listview in the second activity
//create new deckObjet
DeckObject deckObject = new DeckObject();
//get unique id from firebase
String deckId = decksDatabaseReference.push().getKey();
//set unique id to deck object
deckObject.setId(deckId);
//add new deckObject to database
decksDatabaseReference.child(deckId).setValue(deckObject);
//refresh activity to show change in listview
startActivity(new Intent(FlashCardDecks.this, FlashCardDecks.class));
This will crash the app. But when I next open the app, the new deck is there in the second activity. So I don't know why the app is crashing will a null pointer
Here is the error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ec16358.examcompanion/com.ec16358.examcompanion.FlashCardDecks}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.BaseBundle.getString(java.lang.String)' on a null object reference
...
at com.ec16358.examcompanion.FlashCardDecks.onCreate(FlashCardDecks.java:48)
(FlashCardDecks line 48 = String moduleId = extras.getString("EXTRA_MODULE_ID");
)
This worked
if (getIntent().getStringExtra("EXTRA_MODULE_ID") != null && (getIntent().getStringExtra("EXTRA_MODULE_NAME") != null)){
moduleId = bundle.getString("EXTRA_MODULE_ID");
moduleName = bundle.getString("EXTRA_MODULE_NAME");
}
I've used putExtra() to pass some data from one activity to other. I want to create a Parcelable instance but I am getting a null object.
Here is the code of first activity:
i = new Intent(Activity1.this, Activity2.class);
i.putExtra(com.login_app.Activity1.extra, "100");
startActivity(i);
Here is the code of second activity:
Intent inew = getIntent();
Bundle icicle1 = inew.getExtras();
// this is just a debug code
System.out.println(
icicle1.getSerializable(com.login_app.Activity1.extra).toString());
Parcelable p = inew.getParcelableExtra(com.login_app.Activity1.extra);
Here object p is a null object.
Please tell me if I am wrong or I need to add something else. I want this Parcelable object to be flattened into a Parcel object.
That's because you've put String, but trying to get Parcelable. You should use getStringExtra instead.
Also, from Bundle documentation of [getParcelable()][1] (this function is used to actually get extra from Intent's bundle):
Returns the value associated with the given key, or null if no mapping of the desired type exists for the given key or a null value is explicitly associated with the key.
So you basically get null because you have type mismatch.
cancel(getIntent().getExtras().getInt(“notificationID”));
why we use of dot operator in between these methods? as cancel(int) method takes only one integer parameter.it has 3 methods as parametr.....what exactly the code will do..?
This is a short way to write:
Intent intent = getIntent();
Bundle bundle = intent.getExtras(); // or getIntent().getExtras();
int i = bundle.getInt(“notificationID”); // or getIntent().getExtras().getInt(“notificationID”);
cancel(i); // or cancel(getIntent().getExtras().getInt(“notificationID”));
What you do is to invoke methods on the return value of each method.
You should try going through the concepts of object oriented programming first.
To answer your question, getIntent() returns an object of type intent. We call the getExtras() on the Intent object which returns an object of type Bundle. Then we call getInt() on the Bundle object to finally get the int we want to pass to the cancel() method.
The statement is equivalent to :
Intent i = getIntent();
Bundle b = i.getExtras();
int id = b.getInt("notificationID");
cancel(id);
If we don't need any of the intermediate objects, we can write the whole thing in a single line.
Hope that helps.
cancel(getIntent().getExtras().getInt(“notificationID”));.. even here cancel is getting only 1 arguement... because.. getIntent()= returns an intent intent.getExtras = returns the values it stores if extras has some object then .getInt(“notificationID”) = returns an Int value.. So finally only thing remaining is integer...
I have two activities, Activity A and Activity B. I pass objects from Activity A to Activity B using intents. When i make changes to the Object in Activity B the data changes does not get reflected in Activity A. Have i missed out on something?
You are missing the fact that when you pass Object O from Activity A to Activity B via intents, activity B receives a COPY of object O. The way things work is that The object O gets serialized (converted to a sequence of bytes) and that sequence of bytes is then passed to Activity B. Then activity B recreates a copy of object O at the moment it was serialized. Any changes to the original object after it was serialized are not reflected in it's copy.
If both activities are part of the same application then just use a static field (or singleton) to communicate between them.
If you are passing a String, then it will not change since they are immutable.
Edit: See below for an alternative to Intent extras.
If you wish to use the architecture of passing immutable objects in messages you can create an immutable serializable data class. Pass an immutable instance of the data class in the intent using startActivityForResult. When the second activity is completed, send a different instance of the same immutable data class back to the first activity where it is trapped in onActivityResult. So in code, given an immutable class PasswordState.java with public final fields.
public final class PasswordState implements Serializable {
Create an instance of this immutable class and send it to the second activity as in:
private void launchManagePassword() {
Intent i= new Intent(this, ManagePassword.class); // no param constructor
PasswordState outState= new PasswordState(lengthKey,
timeExpire,
isValidKey,
timeoutType,
password,
model.getIsHashPassword(),
model.getMinimumPasswordLength()); // NOT minimumHashedPasswordLength
Bundle b= new Bundle();
b.putSerializable("jalcomputing.confusetext.PasswordState", outState);
i.putExtras(b);
startActivityForResult(i,REQUEST_MANAGE_PASSWORD); // used for callback
}
The second activity returns a new object when it is done.
PasswordState outPasswordState= new PasswordState(lengthKey,
timeExpire,
isValidKey,
timeoutType,
password,
isHashPassword,
minimumPasswordLength);
Bundle b= new Bundle();
b.putSerializable("jalcomputing.confusetext.PasswordState", outPasswordState);
getIntent().putExtras(b);
setResult(RESULT_OK,getIntent()); // call home with data on success only
finish(); // go back <=== EXITS Here
Where it is trapped in Activity one.
// ON_ACTIVITY_RESULT used for callback from ManageKeys.java
protected void onActivityResult(int request, int result, Intent data)
{
switch (request){
case REQUEST_MANAGE_PASSWORD:
if (result == RESULT_OK) { // Success. New password.
try {
PasswordState inMessage= (PasswordState)data.getSerializableExtra("jalcomputing.confusetext.PasswordState");
password= inMessage.password;
timeExpire= inMessage.timeExpire;
isValidKey= true;
writeToPrefs(); // support first launch and incoming tagged sms, save pw
}
catch(Exception e){ // data == null, extras == null
password= "";
isValidKey= false;
timeExpire= PasswordState.LONG_YEAR_MILLIS;
Log.d(Utilities.TAG,"FailedToGetResult",e); // will be stripped at runtime
}
...
break;
}
}
When you are done prototyping and the data objects are stable, you can refactor the code to use parcels instead of serializing objects. Since a copy is being sent between activities using serialization, it could be argued that the use of an immutable object is overkill. Using a mutable object and serializing a mutable object to and from the second activity would simplify the implementation.
Hope that helps.
JAL
This question already has an answer here:
Android Intent.getStringExtra() returns null
(1 answer)
Closed 1 year ago.
I'm having a weird problem when I try to send strings with intents when switching activities.
Here is what I do in class 1:
Intent myIntent = new Intent(SearchText.this, Search.class);
myIntent.putExtra("searchx", spinnerselected);
myIntent.putExtra("SearchText", input);
startActivity(myIntent);
Class 2:
Intent myIntent = getIntent();
searchText=myIntent.getStringExtra("SearchText");
spinnerselectednumber=Integer.parseInt(myIntent.getStringExtra("searchx"));
And using the debugger in the second class, its clear that there is a value in
searchx.
Though the line myIntent.getStringExtra("searchx") returns null .
Why is this?
Try to add .ToString() to myIntent.putExtra("searchx", spinnerselected); so that it is myIntent.putExtra("searchx", spinnerselected.ToString()); This always works for me
Was spinnerSelected a String?
From the Javadoc for Intent
public String getStringExtra(String name)
Since: API Level 1
Description: Retrieve extended data from the intent.
Parameters:
name The name of the desired item.
Returns: The value of an item that previously added with putExtra() or null if no String value was found.
There seems to be many ways to retrieve "extras" - whatever the type of spinnerSelected was, try to retrieve it using the appropriate method.
Eg if it was an int:
public int getIntExtra(String name, int defaultValue)
This code should work:
Bundle extras = getIntent().getExtras();
return extras != null ? extras.getString("searchx")
: "nothing passed in";