getIntent().getSerializableExtra is null - java

I have a POJO class implements Serializable
and I want to transfer an object of this class to another activity with a help Intent and Bundle.
I checked the object before the transfer, it is not null. (Correctly get one of attributes)
put:
private void onFriendClick(FriendHolder holder, int position) {
Intent intent = new Intent(context, ProfileActivity.class);
Bundle extra = new Bundle();
extra.putSerializable(Consts.KEY_USER_JSON, friendList.get(position));
intent.putExtra(Consts.KEY_USER_JSON, extra);
Log.e("onFriendClick", String.valueOf(friendList.get(position).getName()));
context.startActivity(intent);
}
get from another activity:
private void setupProfile() {
Bundle extras = getIntent().getExtras();
if (extras != null) {
profile = (ProfileDTO) getIntent().getSerializableExtra(Consts.KEY_USER_JSON);
Log.e("onFriendClick", String.valueOf(profile.getName()));//NPE this
} else profile = user.getProfile();
}
Caused by: java.lang.NullPointerException: Attempt to invoke virtual
method 'java.lang.String
ru.techmas.getmeet.api.models.ProfileDTO.getName()' on a null object
reference
at ru.techmas.getmeet.activities.ProfileActivity.setupJsonProfile(ProfileActivity.java:103)

You don't need to create a Bundle.
Try doing:
private void onFriendClick(FriendHolder holder, int position) {
Intent intent = new Intent(context, ProfileActivity.class);
intent.putExtra(Consts.KEY_USER_JSON, friendList.get(position));
Log.e("onFriendClick", String.valueOf(friendList.get(position).getName()));
context.startActivity(intent);
}
private void setupProfile() {
if (getIntent().getSerializableExtra(Consts.KEY_USER_JSON) != null) {
profile = (ProfileDTO) getIntent().getSerializableExtra(Consts.KEY_USER_JSON);
Log.e("onFriendClick", String.valueOf(profile.getName()));//NPE this
} else {
profile = user.getProfile();
}
}
But if still want to use the Bundle, you should replace in the code that you posted:
profile = (ProfileDTO) getIntent().getSerializableExtra(Consts.KEY_USER_JSON);
By:
profile = (ProfileDTO) extras.getSerializableExtra(Consts.KEY_USER_JSON);

Related

Trying to seperate OnClickListener() to another class

I'm trying to create an onClickListener for another class, but there's a NullPointerException. I already tried to pass the value of context, but still, it didn't work. I don't know what value is null.
This is the class for ExternalOnClickListener
public class ExternalOnClickListener implements View.OnClickListener{
private Context context;
public ExternalOnClickListener(Context c) {
context = c;
}
public void setRowCol(Intent hardLevelIntent) {
hardLevelIntent.putExtra("rowCount", 6);
hardLevelIntent.putExtra("colCount", 6);
hardLevelIntent.putExtra("difficulty", 3);
}
#SuppressLint("NonConstantResourceId")
#Override
public void onClick(View v) {
//Hard levels intent
Intent hardLevelIntent = new Intent(context, GameActivity.class);
setRowCol(hardLevelIntent);
switch (v.getId()) {
case R.id.btnBack:
Intent intent = new Intent(context, Level_Selection.class);
context.startActivity(intent);
break;
case R.id.btnHard1:
hardLevelIntent.putExtra("hardStageCount", 1);
context.startActivity(hardLevelIntent);
break;
}
}
}
And the btnEndless.onClickListener() here is trying to create an object for the external onClick. But there's a null pointer exception
public class Level_Selection extends AppCompatActivity {
ImageButton btnBack, btnEasy, btnAverage, btnHard, btnEndless;
ImageButton btnHard1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_level__selection);
this.btnBack = findViewById(R.id.btnBack);
this.btnEasy = findViewById(R.id.btnEasy);
this.btnAverage = findViewById(R.id.btnAverage);
this.btnHard = findViewById(R.id.btnHard);
this.btnEndless = findViewById(R.id.btnEndless);
this.btnHard1 = findViewById(R.id.btnHard1);
btnBack.setOnClickListener(v -> {
Intent intent = new Intent(getApplicationContext(), Menu.class);
startActivity(intent);
});
btnEasy.setOnClickListener(v -> {
Intent intent = new Intent(getApplicationContext(), Level_Easy.class);
startActivity(intent);
});
btnAverage.setOnClickListener(v -> {
Intent intent = new Intent(getApplicationContext(), Level_Average.class);
startActivity(intent);
});
btnHard.setOnClickListener(v -> {
Intent intent = new Intent(getApplicationContext(), Level_Hard.class);
startActivity(intent);
});
btnEndless.setOnClickListener(v -> {
btnHard1.setOnClickListener(new ExternalOnClickListener(getApplicationContext()));
btnHard1.performClick();
});
}
This is the error.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.flip, PID: 10862
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageButton.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.flip.Level_Selection.lambda$onCreate$4$Level_Selection(Level_Selection.java:59)
at com.flip.-$$Lambda$Level_Selection$EhORL8AmJ4WhZjndwpPfbUXg1uA.onClick(Unknown Source:2)
at android.view.View.performClick(View.java:6312)
at android.view.View$PerformClick.run(View.java:24811)
at android.os.Handler.handleCallback(Handler.java:794)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:6651)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)
I hope someone answers my question. Thanks in advance!
Try check btnHard1 value, is it null?
Make sure there is ImageButton with id 'btnHard1' in your activity_level__selection layout.
Seems like your R.layout.activity_level__selection, doesn't containt of button which you set click listener or has different id

Android put extra doesn't send extras to another activity

I try to send some values to another activity.
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), recyclerView, new RecyclerTouchListener.ClickListener() {
#Override
public void onClick(View view, int position) {
Intent intent = new Intent(GroupsMain.this, AboutGroup.class);
intent.putExtra("groupName", "Hello");
startActivity(intent);
}
#Override
public void onLongClick(View view, int position) {
}
}));
And so on AboutGroup activity I try to get extra.
1 way:
Bundle extras = getIntent().getExtras();
String name = extras.getString("groupName");
and second way:
Intent intent = new Intent();
String name = intent.getStringExtra("groupName");
But nothing works for me. On AboutGroup activity i get empty string. Please help me fix this problem.
try this
Send:
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
intent.putExtra("groupName", "Hello Anna");
startActivity(intent);
get extra:
String name = getIntent().getStringExtra("groupName");
myTextview.setText(name);

Unable to pass array of objects via intent extras

I'm passing an ArrayList of movie objects from MainActivity to a DetailActivity via an intent.
intent.putExtra(KEY_mFavoriteMovies, mFavoriteMovies);
startActivity(intent);
In this other activity, I'm adding additional movie objects.
mFavoriteMovies(movie);
However, mFavoriteMovies in MainActivity does not appear to contain the additional movie objects.
Is this behavior expected?
That is the expected behaviour because when you modify your array list at DetailActivity you are working with a different instance of your movies list.
You can get the changes you make to the list by starting DetailActivity with startActivityForResult and then sending back the updated list to your MainActivity
You would have something like this at your MainActivity
ArrayList<String> mMovies;
int DETAIL_REQUEST_CODE = 123;
String KEY_FAVORITE_MOVIES = "key-movies";
private void startDetailActivity() {
Intent intent = new Intent(this, DetailActivity.class);
intent.putStringArrayListExtra(KEY_FAVORITE_MOVIES, mMovies);
startActivityForResult(intent, DETAIL_REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DETAIL_REQUEST_CODE && resultCode == RESULT_OK) {
mMovies = data.getStringArrayListExtra(KEY_FAVORITE_MOVIES);
}
}
And you will have to send the updated list from the DetailActivity with something like this:
public void finishDetail() {
Intent resultIntent = new Intent();
resultIntent.putStringArrayListExtra(KEY_FAVORITE_MOVIES, mMovies);
setResult(Activity.RESULT_OK, resultIntent);
finish();
}
Additionally to #JRG answer in order to get updated list in MainActivity you need to start your DetailActivity as startActivityForResult. This will give you an option to return updated array from DetailsActivity using setResult to MainActivity through onActivityResult callback.
Another approach would be to fix it by changing the architecture of an app by separating View part (Activities) from Model (favorite movies).
Approach depends on what is movie list ...
If your movie list is a simple ArrayList of Strings then use
putStringArrayListExtra and getStringArrayListExtra.
If they are Object (separate class) then you should implement
Parcelable and use putParcelableArrayListExtra and
getParcelableArrayList.
If MovieName is an Object/Class then implement Parcelable
import android.os.Parcel;
import android.os.Parcelable;
public class MovieName implements Parcelable {
private String name;
private String year;
public MovieName(String name, String year) {
this.name = name;
this.year = year;
}
public MovieName(Parcel in) {
name = in.readString();
year = in.readString();
}
// Creator
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public MovieName createFromParcel(Parcel in) {
return new MovieName(in);
}
public MovieName[] newArray(int size) {
return new MovieName[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeString(year);
}
#Override
public String toString() {
return "MovieName=[name=" + name + ";year=" + year + "]";
}
}
Inside MainActivity when you are about to startActivity to go to DetailActivity
Intent intent = new Intent(view.getContext(), DetailActivity.class);
ArrayList<String> movieNames = new ArrayList<String>();
movieNames.add("Star Wars");
movieNames.add("Transporter");
movieNames.add("Need for Speed");
intent.putStringArrayListExtra("MOVIE_NAMES", movieNames);
Log.d("Movie Names", "Writing into intent ... " + movieNames.toString());
ArrayList<MovieName> movieNameList = new ArrayList<MovieName>();
movieNameList.add(new MovieName("Star Wars", "1900"));
movieNameList.add(new MovieName("Transporter", "2000"));
intent.putParcelableArrayListExtra("movie", movieNameList);
Log.d("MovieName Parcelable", "Writing into intent ... " + movieNameList.toString());
startActivity(intent);
Inside DetailActivity's onCreate
ArrayList<String> movieNames = getIntent().getStringArrayListExtra("MOVIE_NAMES");
Log.d("Movie Names", "Reading from intent ... " + movieNames.toString());
ArrayList<MovieName> movieNameList = getIntent().getExtras().getParcelableArrayList("movie");
Log.d("MovieName Parcelable", "Reading from intent ... " + movieNameList.toString());
Sample Run
07-25 16:32:53.108 5264-5264/? D/Movie Names: Writing into intent ... [Star Wars, Transporter, Need for Speed]
07-25 16:32:53.111 5264-5264/? D/MovieName Parcelable: Writing into intent ... [MovieName=[name=Star Wars;year=1900], MovieName=[name=Transporter;year=2000]]
07-25 16:32:53.144 5264-5264/? D/Movie Names: Reading from intent ... [Star Wars, Transporter, Need for Speed]
07-25 16:32:53.145 5264-5264/? D/MovieName Parcelable: Reading from intent ... [MovieName=[name=Star Wars;year=1900], MovieName=[name=Transporter;year=2000]]

Passing the selected object to an Another Activity

I have a news activity in which there is a list of news.I want a user to select a news from the list and direct him to the news_details page where I give the details about the selected news, however when the user selects the news, program goes quickly to news_details and comes back again to the news.
News:
public void Listen() {
list.setOnItemClickListener(new AdapterView.OnItemClickListener() { // ana sayfada herhangi bir item seçildiğinde
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
NewsItem selectedNews = (NewsItem) parent.getItemAtPosition(position);
Intent i = new Intent(MainActivity.this, News_Details_Activity.class);
i.putExtra("title", selectedNews.getTitle());
i.putExtra("date", selectedNews.getNewsDate().toString());
i.putExtra("image_id", selectedNews.getImageId());
i.putExtra("text", selectedNews.getText());
setResult(RESULT_OK, i);
startActivity(i);
}
});
}
News_Details:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news__details);
Intent i = new Intent(this,MainActivity.class);
startActivityForResult(i, GET_NEWS);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == GET_NEWS) { // Check which request we're responding to
if (resultCode == RESULT_OK) { // Make sure the request was successful
title.setText(data.getStringExtra("title"));
date.setText(data.getStringExtra("date"));
news_img.setImageResource(data.getIntExtra("image_id", 0));
news_text.setText(data.getStringExtra("text"));
}
}
}
}
First of all, remove this line:
setResult(RESULT_OK, i);
Also, remove this line from newsdetails activity:
startActivityForResult(i, GET_NEWS);
Make changes as below:
public void Listen() {
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
NewsItem selectedNews = (NewsItem) parent.getItemAtPosition(position);
Intent i = new Intent(MainActivity.this, News_Details_Activity.class);
i.putExtra("title", selectedNews.getTitle());
i.putExtra("date", selectedNews.getNewsDate().toString());
i.putExtra("image_id", selectedNews.getImageId());
i.putExtra("text", selectedNews.getText());
startActivity(i);
}
});
}
Then, in your news details activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news__details);
Intent i = getIntent();
String title = i.getStringExtra("title");
String date = i.getStringExtra("date");
int imageId = i.getIntExtra("image_id");
String text = i.getStringExtra("text");
}
OnActivityResult method is not required so simply remove it.
FYI:
startActivity and startActivityForResult both of them start new activities , but startActivityForResult as the name suggests that you are expecting a result from the activity you are starting. And this result shall be obtained in onActivityResult method.
Say for example, you want to start Activity2 from Activity1, and you want to pass some data back to Activity1 while finishing Activity2. You simply set the Result in Activity2 using setResult() method. and while Activity1 resumes again, its onActivityResult() will be invoked, you will override onActivityResult() in Activity1 to receive the Result set by Activity2.
Hope you are now clear on this.
Remove these lines
setResult(RESULT_OK, i);
Intent i = new Intent(this,MainActivity.class);
startActivityForResult(i, GET_NEWS);
Use google Gson for serializing the object.
NewsItem selectedNews = (NewsItem) parent.getItemAtPosition(position);
String strNews = new Gson().toJson(selectedNews);
Intent i = new Intent(MainActivity.this, News_Details_Activity.class);
i.putExtra("news", strNews);
startActivity(i);
On other hand News details onCreate() do this
Bundle bundle = getIntent().getExtras();
String newsStr = bundle.getString("news");
Gson gson = new Gson();
Type type = new TypeToken<NewsItem>() {
}.getType();
NewsItem selectedNews = gson.fromJson(newsStr, type);
to send string value
NewsItem selectedNews = (NewsItem) parent.getItemAtPosition(position);
Intent i=new Intent(MainActivity.this, News_Details_Activity.class);
i.putExtra("title", selectedNews.getTitle());
i.putExtra("date", selectedNews.getNewsDate().toString());
i.putExtra("image_id", selectedNews.getImageId());
i.putExtra("text", selectedNews.getText());
startActivity(i);
to recieve in News_Details_Activity
Intent i = getIntent();
title = i.getStringExtra("title");
date= i.getStringExtra("date");
text= i.getStringExtra("text");
you can do it using Serializable by following way
public class News implements Serializable{
String title;
String desc;
String time,imageUrl;
}
Then News List activity
Intent i = new Intent(MainActivity.this, News_Details_Activity.class);
i.putExtra("news",newsObject);
and get it onCreate of NewsDetail
News news=(News) getIntent().getExtras().getSerializable("news");
and user it like title.setText(news.getTitle());
make News class that implements Serialazable
Create new Object of News class , and put into intent as putSerialazable();
in your second activity just getIntent().getSerialazable("key") and set your data to views.

Error in Intent Service in Android

I am trying to fetch some for Location Address using IntentService but ended up with error leading to app crash. Please help me.
Here is the Stacktrace:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.os.ResultReceiver.send(int, android.os.Bundle)' on a null object reference
at com.example.ajender.sample2.FetchAddressIntentService.deliverResultToReceiver(FetchAddressIntentService.java:91)
at com.example.ajender.sample2.FetchAddressIntentService.onHandleIntent(FetchAddressIntentService.java:81)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.os.HandlerThread.run(HandlerThread.java:61)
Here is FetchAddressIntentService:
public class FetchAddressIntentService extends IntentService {
private static String TAG="Fetch-address-Service";
protected ResultReceiver mReceiver;
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* #param name Used to name the worker thread, important only for debugging.
*/
public FetchAddressIntentService(String name) {
super(name);
}
public FetchAddressIntentService(){
super("FetchAddressIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
String errorMessage = "";
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
Location location = intent.getParcelableExtra(
Constants.LOCATION_DATA_EXTRA);
mReceiver=intent.getParcelableExtra(Constants.RECEIVER);
Log.e(TAG,"1-----");
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocation(
location.getLatitude(),
location.getLongitude(),
// In this sample, get just a single address.
1);
} catch (IOException ioException) {
// Catch network or other I/O problems.
errorMessage = "service_not_available";
Log.e(TAG, errorMessage, ioException);
} catch (IllegalArgumentException illegalArgumentException) {
// Catch invalid latitude or longitude values.
errorMessage = "invalid_lat_long_used";
Log.e(TAG, errorMessage + ". " +
"Latitude = " + location.getLatitude() +
", Longitude = " +
location.getLongitude(), illegalArgumentException);
}
// Handle case where no address was found.
if (addresses == null || addresses.size() == 0) {
if (errorMessage.isEmpty()) {
errorMessage = "no_address_found";
Log.e(TAG, errorMessage);
}
deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
} else {
Address address = addresses.get(0);
ArrayList<String> addressFragments = new ArrayList<String>();
// Fetch the address lines using getAddressLine,
// join them, and send them to the thread.
for(int i = 0; i < address.getMaxAddressLineIndex(); i++) {
addressFragments.add(address.getAddressLine(i));
}
Log.i(TAG, "address_found");
deliverResultToReceiver(Constants.SUCCESS_RESULT,
TextUtils.join(System.getProperty("line.separator"),
addressFragments));
}
}
private void deliverResultToReceiver(int resultCode, String message) {
Bundle bundle = new Bundle();
bundle.putString(Constants.RESULT_DATA_KEY, message);
Log.e(TAG, "2-----");
mReceiver.send(resultCode, bundle);
Log.e(TAG, "3-----");
}
This service should have to send back bundle with Result Receiver and result code but not happening....
The error can be resolved following the steps below
In the MainActivity
Add public AddressResultReceiver mResultReceiver;
mResultReceiver = new AddressResultReceiver(null)- This will automatically assign a id for the main activity class.
In the FetchAddressIntentService
Add mReceiver = intent.getParcelableExtra(Constants.RECEIVER);
Check whether mReceiver is null by logging it.
Send the data using your current code.
It should work. Thats how I got Around it.If you have any problem comment.
Probably you haven't initialize the mResultReceiver from your activity correctly, which you are supposed to pass to the FetchAddressIntentService intent:
mResultReceiver = new AddressResultReceiver(new android.os.Handler());
..
Intent intent = new Intent(this, FetchAddressIntentService.class);
intent.putExtra(Constants.RECEIVER, mResultReceiver);
..
startService(intent);
What happens in case of IntentService is that you have three components that are playing role: MainActivity (that will call the intent service), IntentService (which is responsible for handling the intent) and the last ResultReceiver which receives the result after the intent has been handled (or operated).
As evident from the Log you have not initialized or assigned any value to ResultReceiver mReceiver
You should initialize mResultReceiver by declaring a class let us call it AddressResultReceiver which extends ResultReceiver and has a parameterized constructor that accepts a single parameter as Handler object and overrides the onReceiveResult() method like the following:
AddressResultReceiver(Handler handler) {
super(handler);
}
//Result from intent service
#Override
public void onReceiveResult(int resultCode, Bundle bundle) {
...
}
Now you have successfully obtained two of three components: MainActivity for starting an intent request and ResultReceiver for receiving the result. Let us now make our IntentService by defining a class in the project hierarchy and extending it with IntentService and overriding its method onHandleIntent(Intent intent)():
public class FetchAddressIntentService extends IntentService {
public FetchAddressIntentService() {
super("FetchAddressIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {...}
}
So we are now good to go to get the things up and working. Now write the following code in your MainActivity:
//Initializing the reference with AddressResultReceiver object
mResultReceiver = new AddressResultReceiver(new Handler());
...
//Setting the IntentService to FetchAddressIntentService
Intent intent = new Intent(this, FetchAddressIntentService.class);
/*passing the receiver object to the service so as to let it know where to
publish results*/
intent.putExtra(Constants.RECEIVER, mResultReceiver);
...
//starting the service
startService(intent);
Now your deliverResult(int, String) would no longer throw NullPointerException. For more information visit IntentService and ResultReceiver. Hope it helps! :)
Add the below code in your protected void onHandleIntent (#Nullable Intent intent){} before Geocoder
if (intent != null){
String errorMessage ="";
resultReceiver = intent.getParcelableExtra(Constants.RECEIVER);
Location location = intent.getParcelableExtra(Constants.LOCATION_DATA_EXTRA);
if (location == null) {
return;
}

Categories

Resources