pass Intent to function throws NullPointerException - java

In an Android I would like to pass an Intent Object to a function, but consistently get a NullPointerException.
I could not find any source citing that this is not possible.
basically I have this:
public Intent intent;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
intent = getIntent();
int check = elsewhere.chk_intent(intent); //<=THROWS ERROR
}
chk_intent() performs some functions on data transmitted with the intent, especieally if some extra fields are present.
I tried to move getIntent() into this function, but this is not allowed.
Any help would be much appreciated

Is this activity called by another activity? The intent will not be null only if previous activity supplies an intent to the current activity:
// previous activity
Intent intent = new Intent(FirstActivity.class, SecondActivity.class);
int value = 10;
intent.putIntExtra("key", value);
startActivity(intent);
// use this if want to return data
//startActivityForResult(intent);
If this activity is the starting (main) activity or it is not called by any previous activity, then getIntent() is null, you need to initialize your own new Intent object.
// current activity in onCreate() method
if(getIntent() == null) {
Intent intent = new Intent();
int check = elsewhere.chk_intent(intent);
}

Related

Is there a way to check if I came from a specific activity before starting a new one?

Let's say I have 3 activities: A, B, and C. And all 3 activities can direct the user to one another. Is there a way to check if I came from a specific activity?
For example, to get to C, I can move from B -> C or A -> C. But is there a way for me to check if I came from B?
You can pass data payload through activity intent.pass your activity name for check where user came from.
start activity
Intent intent = new Intent(yourFromActivity.this,yourToActivity.class);
intent.putExtra(bundle_key,yourActivityName);
startActivity(intent)
In your second activity check intent extra and get the activity name where user came from.
#override
protected void onCreate(Bundle savedInstanceState){
//check extra key has in bundle.should same as host activity key
if(getIntent().hasExtra(bundle_key))
{
//get passed value from intent bundle
String activity = getIntent().getStringExtra(bundle_key,"");
if(activity.equel(yourActivityname)){
//put logic here
}
}
}
You can do it by 2 ways which are
Pass extra parameter in Intent when calling activity and in receiver
activity check received parameter and perform task accordingly.
Use startActivityForResult() instead of startActivity() when calling
activity & use getCallingActivity().getClassName() in receiver call to get
class name.
Passing Data in Intent:
Calling class A:
Intent intent = new Intent(A.this,C.class);
intent.putExtra("source","A");
startActivity(intent);
Receiver class C:
in onCreate method
String source;
Intent intent = getIntent();
if(intent.hasExtra("source"))
{
source = intent.getStringExtra("source");
}
//Now you received source class name you can check and perform action
//accordingly.
if(source.equals("A")
{
//For Class A
}
else{
// For Class B
}
Using startActivityForResult():
Sender Class:
Intent intent = new Intent(A.this,C.class);
startActivityForResult(intent);
Receiver Class:
//In onCreate Method get calling activity name
getCallingActivity().getClassName();
try this
Intent intent = new Intent();
intent.setClass(A.this,Receiveractivity.class);
intent.putExtra("Uniqid","From_Activity_A");
A.this.startActivity(intent);
Intent intent = new Intent();
intent.setClass(B.this,Receiveractivity.class);
intent.putExtra("Uniqid","From_Activity_B");
B.this.startActivity(intent);
Intent intent = new Intent();
intent.setClass(C.this,Receiveractivity.class);
intent.putExtra("Uniqid","From_Activity_C");
C.this.startActivity(intent);
Intent Activity
//obtain Intent Object send from SenderActivity
Intent intent = this.getIntent();
/* Obtain String from Intent */
if(intent !=null)
{
String strdata = intent.getExtras().getString("Uniqid");
if(strdata.equals("From_Activity_A"))
{
//Do Something here...
}
if(strdata.equals("From_Activity_B"))
{
//Do Something here...
}
if(strdata.equals("From_Activity_C"))
{
//Do Something here...
}
........
}
else
{
//do something here
}

How do I create a new object on every button click?

I am creating a notes app, and I've all but finished it. My app starts on the main activity, which shows a recylcerView displaying all of the saved notes. To create a new note, you press a button, which sends you to another activity where you write your note. You then press a button that saves the note as an instance of the Note class and sends that object instance back to the main activity where it updates the recyclerView.
My problem is, every time I press the save button for my note, it just updates the Note instance instead of creating an entirely new one. How do I get it to create a new instance of the Note class so that I can have more than one saved note?
Here is my code for the save button:
Intent intent = new Intent(AddNoteActivity.this, MainActivity.class);
String mTitle = title.getText().toString();
String mContent = content.getText().toString();
intent.putExtra("notePar", new Note(mTitle, mContent));
startActivity(intent);
Here is my code for the mainactivity:
Intent intent = getIntent();
Note sentParcNote = intent.getParcelableExtra("notePar");
if(sentParcNote != null) {
notes.add(sentParcNote);
}
You are using startActivity(intent) to navigate from AddNoteActivity to MainActivity, this method is used to start a new activity, which means, the system will create a new instance of MainActivity class and put it at the top of the activity stack. This way you will always have 0 or 1 note (when sentParcNote != null)
I would suggest to use startActivityForResult when you navigate from MainActivity to AddNoteActivity and call setResult in your AddNoteActivity
Example:
MainActivity:
Declare this static int at the top of your class (e.g: just before onCreate method)
private static final int ADD_NOTE_ACTIVITY_REQUEST_CODE = 2;
Then add this piece of code on your button action to start AddNoteActivity:
Intent addNoteIntent = new Intent(this, AddNoteActivity.class);
startActivityForResult(addNoteIntent, ADD_NOTE_ACTIVITY_REQUEST_CODE);
Then to catch the new note from AddNoteActivity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ADD_NOTE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Note sentParcNote = data.getParcelableExtra("notePar");
if(sentParcNote != null) {
notes.add(sentParcNote);
}
}
}
}
AddNoteActivity:
add this piece of code to your save button action
String mTitle = title.getText().toString();
String mContent = content.getText().toString();
Intent intent = new Intent();
intent.putExtra("notePar", new Note(mTitle, mContent));
setResult(RESULT_OK, intent);
// finish closes the current activity which means in this case it goes back to the MainActivity
finish();
I would suggest using local storage to save your notes otherwise if you restart the app you will always have 0 notes.

How do you pass data back and forth between activities in Android?

I have two activities that should pass data back and forth to each other using intents. I'm not sure where to place some of the puts and gets though.
For Activity1 (MainActivity), I have a button, and on press it creates an intent, and then puts it to Activity2, then starts it using startActivity(intent).
btn.setOnClickListener((v) -> {
Intent intent = new Intent(this, Activity2.class);
intent.putExtra("test", testClass);
startActivity(intent);
});
Then in Activity2, I get that information in the onCreate() function using getIntent.
Now what I want to do is have a button in Activity2 that will pass data to Activity1, but won't necessarily "start/show" the activity.
So I'm wondering how this can be done.
My idea is to have the following similar to before:
Activity2:
btn.setOnClickListener((v) -> {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("info", info);
});
But I'm confused about two things
Can I do this without starting the activity right away
Where would I do the getIntent call in MainActivity to retrieve this data
You can use startActivityForResult to start Activity2 and receive a result back to Activity1
Activity 1
int LAUNCH_ACTIVITY_TWO = 1;
Intent i = new Intent(this, Activity2.class);
i.putExtra("test", testClass);
startActivityForResult(i, LAUNCH_ACTIVITY_TWO);
//onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LAUNCH_ACTIVITY_TWO) {
if(resultCode == Activity.RESULT_OK){
String result=data.getStringExtra("result");
}
}
}
Activity 2
Intent returnIntent = new Intent();
returnIntent.putExtra("result", result);
setResult(Activity.RESULT_OK, returnIntent);
finish();
Full Activity 1 code:
public class MainActivity extends AppCompatActivity {
public static int LAUNCH_ACTIVITY_TWO = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener((v) -> {
Intent i = new Intent(this, Activity2.class);
i.putExtra("test", testClass);
startActivityForResult(i, LAUNCH_ACTIVITY_TWO);
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LAUNCH_ACTIVITY_TWO) {
if(resultCode == Activity.RESULT_OK){
String result= data.getStringExtra("result");
}
}
}
}
Full Activity 2 code:
public class Activity2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(getIntent().getExtras() != null) {
// Get intent extras from Activity 1
}
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener((v) -> {
Intent returnIntent = new Intent();
returnIntent.putExtra("result", result);
setResult(Activity.RESULT_OK, returnIntent);
finish();
});
}
}
You can for example create a list in activity2 to which you add the data you want to pass to activity1. Before starting activity1 you get the values out of your array and add them as extras to the input.
You can have the data added to a JSONObject and use a serializer so you don't have to add your items all by yourself.
If you want to pass your data to activity1 without starting it,so activity1 processes the data, that is not possible. Activity doesnt execute anything while you are in activity2, for such cases you use fragments.
If you use fragments you can put all data in a viewmodel which is bound to the activity instead of each fragment.
There are several ways you can achieve this pending on what type of data you're looking at passing.
If it's an entire class object then make the class parcable. You can copy and paste the class in this website http://www.parcelabler.com/ and it auto formats it for you. All you do is pass it as an intent extra.
If you're looking at data that needs an action performed on it and then passed to another activity I would suggest using and intent service. You can perform certain actions pending the intents received in the service.
If you're looking at performing certain actions only after XYZ has occurred in your application then used shared preferences. These can be accessed anywhere quite easily.
Lastly, if you're using bulk data consistently that needs to remain persistent, use a local database storage and just query when you need to.
You can use SharedPreferences or static variables/fields for that.

Starting an Activity from a Notification and passing data onBackPressed

I have 3 Activities on the app:
MainMenuActivity -> ExecuteTrainingActivity -> ExecuteExerciseActivity.
From MainMenuActivity to ExecuteTrainingActivity, I'm passing an idExecution and an idExercise for ExecuteTrainingActivity query and load the initial data.
ExecuteTrainingActivity onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
initialize();
setupRecyclerView(exercises);
}
private void initialize() {
Bundle extras = getIntent().getExtras();
if (extras != null) {
if (extras.containsKey("id_execution")) {
idExecution = extras.getLong("id_execution");
idExercise = extras.getLong("id_exercise");
execution = queryExecution(idExecution);
} else {
insertExecution();
}
}
}
In the 3rd activity, ExecuteExerciseActivity, I have a TimerFragment that, and when TimerCountdown reaches 0, it opens a Notification popup, that when clicked open an fresh ExecuteExerciseActivity.
On this TimerFragment, I'm passing as Extras the same ids, so I can get them in the new fresh ExecuteExerciseActivity:
public class TimerFragment extends Fragment {
//...
private void showNotification(){
Intent intent = new Intent(getActivity(), ExecuteExerciseActivity.class);
intent.putExtra("id_execution", idExecution);
intent.putExtra("id_exercise", idExercise);
intent.putExtra("position", position);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getActivity());
stackBuilder.addNextIntentWithParentStack(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
/*=== CHECK IF NOTIFICATION CHANNEL IS ACTIVE ===*/
boolean ok = isNotificationChannelEnabled(getActivity(), Constants.CHANNEL_ID);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(requireNonNull(getActivity()), Constants.CHANNEL_ID)
.setSmallIcon(R.drawable.d77)
.setContentTitle("Teste Notificação")
.setContentText("Ababa")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getActivity());
notificationManager.notify(0, mBuilder.build());
}
From this new fresh ExecuteExerciseActivity, I want to make the system maintain the same navigation flow of Activities, but when I backpress from the new ExecuteExerciseActivity to ExecuteTrainingActivity, i can't pass the Id's for the ExecuteTrainingActivity query and load.
Is there a way to pass arguments onBackPress?
Is the best approach override onBackPress creating a new intent and a starting a new Activity?
**My manifest is using parentActivityName correctly.
Save your query and id into a SharedPreferences in onDestroy of your ExecuteExerciseActivity then pull out the query and id again in the old ExecuteTrainingActivity. onBackPressed triggers onDestroy event of an activity's life cycle. Then in the onResume of ExecuteTrainingActivity pull this data back out.
I think you can achieve this by overriding onOptionsItemSelected() method of ExecuteExerciseActivity. Try this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
Intent intent = new Intent(this, ExecuteExerciseActivity.class);
//Add the extras to the intent
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
In Android, if your Activity starts another Activity and want to pass data to that Activity, you would add those data as Intent extras.
This Activity A to Activity B type of sending data is something you're using already.
But for Activity B back to Activity A, there's actually a built-in solution for this, which is through startActivityForResult(Intent, REQUEST_CODE) instead of startActivity(Intent).
Now in Activity B, you simply have to code:
#Override
public void onBackPressed()
{
Intent resultIntent = getIntent();
resultIntent.putExtra(EXTRA_NAME, extra_value);
setResult(Activity.RESULT_OK, resultIntent);
finish();
}
Basically, in Activity B, you're setting the data you want to send back to the Activity A that started Activity B, since there's a connection between these two Activities.
Next, in your Activity A, just override the onActivityResult() method.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// get data through data.getIntExtra() and etc
}
}
}
The request code needs to match the REQUEST_CODE you used for Activity B, so Activity A knows which Activity to respond to. The result code is just a quick way for you to categorize the type of result you're getting back from Activity B, since there might be more than one type of result being returned from Activity B.
This solution of passing data is better than creating a new Intent and starting a new Activity because you don't need to start a new Activity. Your Activity A already exists, so there's no reason to rebuild the entire layout, reload all the data, and have a new Activity existing on the Activity stack.
Since your only intention is to pass data from Activity B back to the Activity A that started it, use startActivityForResult() and onActivityResult() to handle this type of data sharing.

Can startActivityForResult() send data?

I am learning android and curious to know as if startActivityForResult() contains the properties of startActivity() too, i.e. can it be used to send data like startActivity() beside receiving data from called activity?
Here is the code:
SendData Activity:
Intent data= new Intent(SendData.this, RecieveData.class);
Bundle check = new Bundle();
check.putString("UmerData", cheese);
medt.setText(cheese);
data.putExtras(check);
startActivityForResult(data, 5);
Should receive data in this activity (RecieveData Activity)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recievedata);
Initializek();
Bundle got = getIntent().getExtras();
String ss= got.getString("UmerData");
if(getIntent()!=null && ss!=null ) {
rt1.setText("Is not Null");
}
}
Your help will be really appreciated !
Thanks
Yes, startActivity & startActivityForResult, both take intent as param. You can bundle launch data inside intent and pass it over to target activity.
When you use startActivityForResult(), you have to also create a onActivityResult() method within the Activity that called startActivityForResult(). onActivityResult() is where you can access the Intent stored by the Activity you start for a result.
In the Activity that is then started, you have to call setResult() to store the Intent that you store the data in.
Read over this: http://developer.android.com/reference/android/app/Activity.html#StartingActivities
edit: Misread your question. For passing a Bundle of options through, I would use this overload:
startActivity(Intent, int, Bundle)
I'm working in Xamarin Android so the code is C# but I had the same problem except I'm sending between separate apps. I eventually got it working so here is my example.
var intent = new Intent();
intent.SetComponent(new ComponentName("com.company.packageName", "com.company.packageName.activityName"));
intent.PutExtra(Intent.ExtraText, message);
StartActivityForResult(intent, 1);
// in app being started
protected override void OnResume()
{
base.OnResume();
Intent intent = Intent; // Equivalent to getIntent()
if (intent != null)
{
string str = intent.GetStringExtra(Intent.ExtraText);
if (str != null)
{
// Do stuff with str
}
else
{
//Show Error
}
}
else
{
//Show Error
}
}

Categories