I'm trying to send messages through in built sms app through Intent. Its working fine. Here is my code
public class Main_Act extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button startBtn = (Button) findViewById(R.id.button);
startBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if(sendSMS()) {
Intent intent = new Intent(Main_Act.this, Sample.class);
startActivity(intent);
}
}
});
}
protected boolean sendSMS() {
ArrayList<String> nums = new ArrayList<String>();
nums.add("111111111");
nums.add("222222222");
Log.i("Send SMS", "");
Intent smsIntent = new Intent(Intent.ACTION_VIEW);
smsIntent.setData(Uri.parse("smsto:"));
smsIntent.setType("vnd.android-dir/mms-sms");
smsIntent.putExtra("address" ,nums);
smsIntent.putExtra("sms_body" , "Test ");
try {
startActivity(smsIntent);
finish();
return true;
}
catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(Main_Act.this,
"SMS faild, please try again later.", Toast.LENGTH_SHORT).show();
return false;
}
}
}
But the problem is it gets navigated to another activity without clicking send button in sms application. It should goto another activity only after clicking the send button in messaging app. Can anyone help me with this problem, Thanks in advance.
Let's clear out a slight misunderstanding in your code:
You should not try to start both intents in the same part/run of the code as you do here.
A startActivity will not execute directly going to the activity and then return to the same place in the code when activity execution finishes. In stead it asynchronously queues the intent for execution. Then your code queues another intent for execution. After the current code finishes (in this case when the button onClick() method ends) Android queue mgmt can start picking off the queue. Probably the first intent is executed shortly and then directly overrun by an immediate execution of the second.
So what happens in summary is that you first add one intent to the queue in sendSMS and then add intent 2 to the queue in onClick, before leaving. Now both the intents are executed.
What you need to do is to change the sendSMS code to something like:
Intent smsIntent = new Intent(Intent.ACTION_VIEW);
smsIntent.setData(Uri.parse("smsto:"));
smsIntent.setType("vnd.android-dir/mms-sms");
smsIntent.putExtra("address" ,nums);
smsIntent.putExtra("sms_body" , "Test ");
// To force the SMS app to return immediately after sent SMS
smsIntent.putExtra("exit_on_sent", true);
startActivityForResult(smsIntent, MY_SMS_REQUEST_RESPONSE_CODE);
Note the startActivityForResult() method that indicates that we expect Android to return and the "exit_on_sent" extra, to force a swift return.
MY_SMS_REQUEST_RESPONSE_CODE is just any random code you select to recognize the returning result in the callback method (even if you currently do not expect any other returning results, you may have some in the future).
Next thing to do is to remove the second intent creation and queuing. In stead you implement the following callback method (added to this activity):
#Override
protected void onActivityResult(
int callbackIdentifier, int resultCode, Intent intent) {
// Is this the expected sendSMS callback ?
if (callbackIdentifier== MY_SMS_REQUEST_RESPONSE_CODE) {
if (resultCode == RESULT_OK) {
// Continue where you left off (e.g. execute intent 2)
Intent intent = new Intent(Main_Act.this, Sample.class);
startActivity(intent);
} else if (resultCode == RESULT_CANCELED) {
// Error handling/retrying etc
}
}
// Support inherited callback functions
super.onActivityResult(callbackIdentifier,resultCode,intent);
}
Note: if you want to pass data and type don't call method separately because will delete each other you must pass it in one method
wrong
smsIntent.setData(Uri.parse("smsto:"));
smsIntent.setType("vnd.android-dir/mms-sms");
true
smsIntent.setDataAndType(Uri.parse("smsto:"),"vnd.android-dir/mms-sms");
Related
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.
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.
I have some problems handling http response codes. The problem is that the app crashes because I do not give a specific function to run.
In this case I want to send the user back to login screen when the Httresponsecode is 401 otherwise the user can still use the app.
In my current code I have the following:
public boolean isUnauthorized(JSONObject response){
try {
if(response.getInt("StatusCode") == 401) {
return true;
}
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
What I want is here is to call so that when calling this function app wide it will do the same on every screen.
Intent i = new Intent(Register.class, Register.activity);
startactivity(i);
However this isn't possible because the ResponseHandler cannot extends Activity. If I do this I get a stack-trace error containing looper.prepare() must be called.
Can you anybody tell me how I can call a new intent from here. The class containing above is in a folder called components and my app activities are in another folder in case it is needed for giving the right answer.
Intent i = new Intent(Register.class, Register.activity);
startactivity(i);
This should be
Intent i = new Intent(CurrentClass.this, Activity.class);
startactivity(i);
if you have fragment
Intent i = new Intent(getActivity(), Activity.class);
getActivity().startactivity(i);
You need to pass the current Activity or the Application Context as argument for your Intent.
If it is inside a fragment then
getActivity().startActivity(getActivity(), newActivity.class);
If it is inside a class then:
context.startActivity(context, newActivity.class);
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
}
}
I created my lockscreen application that trigerred by a SMS.. i have ListenSMS class that always listen for incoming SMS. Here's the code :
for (SmsMessage message : messages) {
String tempMessage[] = message.getDisplayMessageBody().toString().split(" ");
//checking command dan password
if (tempMessage[0].toString().equalsIgnoreCase("andro-lock") && tempMessage[1].toString().equals(tempPassword.toString())) {
//Toast.makeText(ListenSMSservice.this, "Menjalankan command andro-lock", Toast.LENGTH_LONG).show();
openDatabase();
updateStatusL();
Intent myIntent = new Intent(ListenSMSservice.this,LockScreenForm.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(myIntent);
}
else if (tempMessage[0].toString().equalsIgnoreCase("andro-unlock") && tempMessage[1].toString().equals(tempPassword.toString())) {
//Toast.makeText(ListenSMSservice.this, "Menjalankan command andro-unlock", Toast.LENGTH_LONG).show();
openDatabase();
updateStatusNL();
Intent myIntent = new Intent(ListenSMSservice.this,LockScreenForm.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Bundle myKillerBundle = new Bundle();
myKillerBundle.putString("kill","1");
myIntent.putExtras(myKillerBundle);
getApplication().startActivity(myIntent);
}
}
If ListenSMS service has received an andro-lock command, it will go to the lockscreen.java and will go to the lockscreen.java with intent extra (putExtra) kill when it receive command andro-unclock. Here's my lockscreen.java:
public class LockScreenForm extends Activity implements OnClickListener {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.lockscreen);
Bundle extra = getIntent().getExtras();
if (extra == null) {
return;
}
//Toast.makeText(this, extra.getString("kill"), 1).show();
else if(this.getIntent().getExtras().getString("kill").equalsIgnoreCase("1")) {
try {
Toast.makeText(this, "extra accepted", 1).show();
finish();
} catch (Exception e) {
// TODO: handle exception
Toast.makeText(this, e.getMessage(), 1).show();
}
}
}
}
I want to close my locksreen.java when my ListenSMS service has received "andro-unlock" command, so I put extra on intent "kill" and check it in lockscreen.java. This lockscreen.java can check the extra intent and can display a toast "extra accepted" but can close the lockscreen activity with finish().
My assumption is for now that Intent.FLAG_ACTIVITY_NEW_TASK is duplicating a locksreen activity. So it will create a double lockscreen activity and the finish method is closing another lockscreen.java that started by Intent.FLAG_ACTIVITY_NEW_TASK. That's only assumption. Am i wrong? Please correct me.
Has anyone know how to solve my problem? I really want that "andro-unlock" command can close the lockscreen activity and need it works for my college final project. Please help.
From http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_NEW_TASK:
When using this flag, if a task is already running for the activity you are now starting, then a new activity will not be started; instead, the current task will simply be brought to the front of the screen with the state it was last in. See FLAG_ACTIVITY_MULTIPLE_TASK for a flag to disable this behavior.
I expect your problem is somewhere else. I'd suggest having the lockscreen Activity register a BroadcastReceiver, and then when the unlock message is received send an Intent that the BroadcastReceiver will catch. The Activity can then cleanly exit.
Try this: Intent.FLAG_ACTIVITY_NEW_TASK