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.
Related
So for one of my personal projects I want to pass an arraylist of ZipEntry objects from one activity to another but I am unable to do so. I have tried the following things:
Creating Bundle() and passing that bundle using putExtra()
Passing ArrayList directly using putExta()
Creating bundle & passing it using putExtra():
Implementation:
// Add data to intent and launch install activity
val newActIntent = Intent(this, InstallActivity::class.java)
val data = Bundle()
data.putSerializable("x", languageListAdapter.selectedItems)
newActIntent.putExtra("z", data)
this.startActivity(newActIntent)
Error:
java.lang.IllegalArgumentException: Parcel: unknown type for value split_config.en.apk
Passing ArrayList<> directly using putExtra()
Implementation:
val newActIntent = Intent(this, InstallActivity::class.java)
newActIntent.putExtra("x", languageListAdapter.selectedItems)
this.startActivity(newActIntent)
Error:
java.lang.IllegalArgumentException: Parcel: unknown type for value split_config.en.apk
Note: ZipEntry object is java.util.zip.ZipEntry
In order to send an ArrayList<ZipEntry> from one Activity to another you need to make sure that your ZipEntry object is serializable, you can do it by implementing Serializable interface.
You can also use Parcelable as an alternative of Serializable.
If you use Serializable you use getSerializableExtra and if it's Parcelable you use getParcelableArrayListExtra
#Parcelize
data class ZipEntry : Parcelable
Fixed this issue thanks to the comment from #wambada
Implementation:
Created a singleton object to store the ArrayLists
object ZipEntrySingleton {
var aList: ArrayList<ZipEntry>? = null
var lList: ArrayList<ZipEntry>? = null
}
Created the singleton object in activity 1 and passed the data to it.
// Add data to intent and launch install activity
val newActIntent = Intent(this, InstallActivity::class.java)
val x = ZipEntrySingleton
x.aList = xListAdapter.selectedItems
x.lList = yListAdapter.selectedItems
this.startActivity(newActIntent)
Retrieved the data in the new activity by using:
ZipEntrySingleton.aList
I don't understand why I cannot Bundle both a Parcelable object and a primitive in the same Bundle. See below.
Bundle bundle = new Bundle();
bundle.putInt("num", 4); // I like 4.
bundle.putParcelable("myObject", myObject);
Intent localIntent = new Intent(SendingClass.this, ReceivingClass.class);
localIntent.putExtras(bundle);
startActivity(localIntent);
And my ReceivingClass' onCreate(Bundle savedInstanceState), (which i'm aware that the sIS is null here)...
Bundle bundle = getIntent().getExtras();
int num = bundle.getInt("num");
MyObject myObject = (MyObject) bundle.getParcelable("myObject");
I would have expected both num and myObject to contain something, however, myObject is populated, but num is always 0.
If I remove the putParcelable and getParcelable lines however, "num" is then correctly populated (with 4).
Looking at the bundle, it seems to only populate with a Parcelable object if it has one, and "drops" all other primitives. Why is this? I haven't been able to find documentation saying Bundles cannot contain both primitives and Parcelables, what gives?
P.S. I have tried to add both the primitive to the Bundle first, and after the Parcelable, but no dice either way.
As expected, it was due to an error in my Parcelable class.
If your public void writeToParcel(Parcel paramParcel, int paramInt){ method writes too many things for the "make object from Parcel' method public ParcelableClass(Parcel paramParcel) {, you will get strange errors in your log, this is what is causing the issue.
Make sure the read and write methods have the same number of read/writes, and of the correct data types.
In my case I was writing 4 objects, (2 Parcelable, 2 primitives), but only reading the 2 Parcelables, and 1 primitive. It just seems strange that some objects made it through ok.
I always thought that when I am passing custom parcelable object, by calling getParcelable(), it will return a totally new object. This is true when I am passing a parcelable object from one Activity to another Activity by putting that parcelable in the Bundle (Bundle is put in Intent).
But when I am trying to pass a parcelable object from a Activity to a background thread which has a Handler attach to, I don't get a new object which means if I modify the value of that object in the background thread, it will affect the object in Activity as well. How come? What have I done wrong?
This time the object is put in Bundle but the Bundle is put in Message, this is the only difference I can find when compare this to passing Parcelable between Activity.
//simple code sample, overwrite handleMessage() of Handler
public void handleMessage(Message msg) {
SkCounter sc = msg.getData().getParcelable("abc");
sc.testing = 99999; //if I change this value here, the object's value from Activity will change too. getParcelable() should create totally new object and changing value of it shouldn't affect other object, right? But how come this happens?
}
Anyone knows why?
When passing a Bundle object from Activity to another Activity, Android framework will parcel and unparcel your object, the unparcel process will create a new object;
When passing a Bundle object through Message, Message.setData() just set the object, without doing parcel, so you are accessing the same object.
you can check Bundle source, your data is stored either in a Map or Parcel:
// Invariant - exactly one of mMap / mParcelledData will be null
// (except inside a call to unparcel)
/* package */ Map<String, Object> mMap = null;
/*
* If mParcelledData is non-null, then mMap will be null and the
* data are stored as a Parcel containing a Bundle. When the data
* are unparcelled, mParcelledData willbe set to null.
*/
/* package */ Parcel mParcelledData = null;
the Bundle.unparcel() method recreates your objects from Parcel.
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...
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";