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);
Related
I'm trying to open the MainActivity when the user clicks a button in my notification, while the app is only running in the background with a service. When the button is clicked, these lines are triggered in the Service class:
Intent openApp = new Intent(this, MainActivity.class);
openApp.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(openApp);
I've checked it, and the lines are triggered, so there's no problem in reacting to the button's click, the Activity won't open though.
Any suggestions? Why isn't this working for me and how can I make it work?
Edit
I was asked for some more code, so in my onStartCommand() inside my Service, if it starts with a stop-action within its intent, I call the killService() method, which kills the Service, starts the MainActivity and do some other stuff:
if (action != null && action.equals(ACTION_STOP_SERVICE)) {
killService();
}
To set the Notifications button, I use this code:
Intent stopActionIntent = new Intent(this, TimerService.class);
stopActionIntent.setAction(ACTION_STOP_SERVICE);
PendingIntent stopActionPendingIntent = PendingIntent.getService(this, 1, stopActionIntent, PendingIntent.FLAG_IMMUTABLE);
timerNotificationBuilder.addAction(R.drawable.stop, "Stop", stopActionPendingIntent);
And as I said, the button already reacts to the user clicking on it, so that's not the problem.
You can try to receive the click in a BroadcastReceiver and then open activity from there.
Try this to add a action button o your notification:
timerNotificationBuilder.addAction(createNotificationActionButton("STOP");
Where the createNotificationActionButton method is this:
public NotificationCompat.Action createNotificationActionButton(String text){
Intent intent = new Intent(this, StopwatchNotificationActionReceiver.class);
#SuppressLint("InlinedApi") PendingIntent pendingIntent = PendingIntent.getBroadcast(this, new Random().nextInt(100), intent, PendingIntent.FLAG_IMMUTABLE);
return new NotificationCompat.Action(0, text, pendingIntent);
}
Create a class named StopwatchNotificationActionReceiver and make it extent a BroadcastReceiver`. This is the code for that class:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class StopwatchNotificationActionReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
PrefUtil.setIsRunningInBackground(context, false);
PrefUtil.setTimerSecondsPassed(context, 0);
PrefUtil.setWasTimerRunning(context, false);
context.stopService(MainActivity.serviceIntent);
Intent activityIntent = new Intent(context, MainActivity.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActvity(activityIntent);
}
}
Also you need to register that receiver in your manifest like this:
<receiver android:name="StopwatchNotificationActionReceiver"/>
Where the MainActivity.serviceIntent is a public static variable which looks like this:
public static Intent serviceIntent;
And this intent is only used to start the service like this:
//In onCreate
serviceIntent = new Intent(this, TimerService.class);
//In onPause
PrefUtil.setTimerSecondsPassed(this,seconds);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent);
}
Or you can try the simple method:
if (action != null && action.equals(ACTION_STOP_SERVICE)) {
Context context = this;
Intent activityIntent = new Intent(context, MainActivity.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActvity(activityIntent);
killService();
}
Edit
Another solution is here. Again. You need to refer to my repo as I have made changes to the files in order to complete your task. In the service class, refer to this method. There, I start the activity if the action is reset(r). Or else, it opens the broadcast receiver. Then, in the activity, I receive that extra in the onResume() method. If the reset button is not clicked, it opens the Receiver class.
And as always, you can view the result of the app from here.
I hope that code will do your work.
I found it! See this answer.
This answer suggests enabling ScreeanOverlay settings because as of Android 10 and later you can no longer open an activity from the background just by calling the lines I've used.
To make it work, you'd have to add this permission through your Manifest.xml:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
And then the user would have to enable the Display over other apps setting.
I searched for an option to get the user to this setting more easily and found this answer.
This answer gives a code that redirects the user to the Display over other apps setting
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 0);
}
and then I guide the user with the notification's content (text) on how to enable the setting.
Once the setting is enabled, The lines I've used before work.\
So, problem solved?
Not Completely Solved
this whole configuration described above works, but only if the app is not killed.
If the app was killed and I try the method listed above, the app joins the recent apps list, but won't open and show up.
A solution that solves this issue as well will be accepted as an answer instead of this one.
My app contains a simple Fragment that is used to open external web pages, with:
Intent intent = new Intent(Intent.ACTION_VIEW, externalUrl); // Uri
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent chooserIntent = Intent.createChooser(intent, "Open URL...");
startActivityForResult(chooserIntent, RC_OPEN_URL);
And, when the result is returned (in my Fragment's onActivityResult(...)), the Fragment is popped off the backstack.
But, I'm now getting the new deprecation warning:
startActivityForResult(Intent,int) in Fragment has been deprecated
I've read the corresponding Getting a result from an activity documentation, but I'm not sure how to adapt the example they provide for my particular case.
I have discovered the ActivityResultContracts.StartActivityForResult class, but can't figure out how to pass my chooserIntent to it.
All the online examples for the class seem to be in Kotlin and I've not had any joy trying to decompile them to Java. So a Java example of how to use the new registerForActivityResult() method to open an external URL would be much appreciated.
There's no reason to use startActivityForResult() at all for createChooser() - you can use startActivity and run your code from onActivityResult() immediately after you call to startActivity:
Intent intent = new Intent(Intent.ACTION_VIEW, externalUrl); // Uri
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent chooserIntent = Intent.createChooser(intent, "Open URL...");
startActivity(chooserIntent);
// Do your code from onActivityResult() here
However, if you really want to use the Activity Result API, then you can directly adapt the examples in the documentation, replacing the example GetContent contract with the StartActivityForResult contract:
// Create this as a variable in your Fragment class
ActivityResultLauncher<Intent> mLauncher = registerForActivityResult(
new StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
// Do your code from onActivityResult
}
});
private void triggerChooser(Uri externalUri) {
Intent intent = new Intent(Intent.ACTION_VIEW, externalUrl); // Uri
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent chooserIntent = Intent.createChooser(intent, "Open URL...");
mLauncher.launch(chooserIntent);
}
Below answer may help to someone.... But this is not readymade solution to above question.
I have faced lot of issue when I try to get result from activity to fragment.
Finally I found below solution.
In side the fragment, I created ActivityResultLauncher.
var myActivityResultLauncher: ActivityResultLauncher<Intent> = registerForActivityResult<Intent, ActivityResult>(
ActivityResultContracts.StartActivityForResult(),
ActivityResultCallback<ActivityResult> {
// ToDO:
if (it.resultCode == AppCompatActivity.RESULT_OK) {
}
}
) as ActivityResultLauncher<Intent>
And when I start the activity I used below code.
myActivityResultLauncher.launch(myIntent)
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");
I want to start another activity in finish() depending on a condition. I got the same code working in onDestroy() but I think this is not the right place from the lifecycle point of view.
(Activities might be destroyed, although there were not actively left by the user).
The following code did not have any effect:
#Override
public void finish() {
if (mCondition) {
Intent intent = new Intent(this, OtherActivity.class);
startActivity(intent);
}
super.finish();
}
Why is it not working, are there alternatives?
I think the best option is starting the new activity then finish the current one:
if (mCondition) {
Intent intent = new Intent(this, OtherActivity.class);
startActivity(intent);
finish();
}
I have Used Myself this and it is working fine
public void ToBeClosed()
{
Intent a = new Intent(context,NewActivity.class);
startActivity(a);
OldActivity.this.finish();
}
and use the function in if statement body
if (mCondition) { ToBeClosed(); }
Having a very annoying problem with passing data between activities.
This is the code I use to successfully pass the value of a progress bar to a different activity:
public void WhenClicked(View view)
{
view.clearAnimation();
Intent intent = new Intent("com.android.Test.QUESTION");
if (progressBar != null)
{
if (progressBar.getProgress() != 0)
{
intent.putExtra("ProgressBarValue", progressBar.getProgress());
}
}
startActivity(intent);
}
Okay, so that worked. Now, when I change it to this, it blows up:
public void WhenClicked(View view, String category)
{
view.clearAnimation();
Intent intent = new Intent("com.android.Test.QUESTION");
intent.putExtra("Category", category);
if (progressBar != null)
{
if (progressBar.getProgress() != 0)
{
intent.putExtra("ProgressBarValue", progressBar.getProgress());
}
}
startActivity(intent);
}
I don't understand what the problem is. I've even tried sticking it all into a bundle and adding the bundle as an extra - that just made it crash as well. Maybe I'm being stupid and I've just been staring at my code too long, but any help would be great!
This is my first time with Android and it's killing me!
Thanks in advance guys!
first you need to create bundle object(Bundle bnd=new Bundle();) and next bnd.putString("param1", "test");
next create intent:
Intent myIntent = new Intent(current classname.this,nextactivity.class);
myIntent.putExtras(bnd);
startActivityForResult(myIntent, 0);
In 2nd activity u need to get bundel value like :
Bundle bundle = this.getIntent().getExtras();
String _getData=bundle.getString("param1");
Assuming that you have an activity called QUESTION, you might try to put .class on the end as well as "this" for first param:
Intent intent = new Intent(this, QUESTION.class);
if you don't have a QUESTION activity then that is another problem. I'm assuming your activities are in the same app?
I believe, the activity which should handle this intent action com.android.Test.QUESTION does not understand your category i.e intent.putExtra("Category", category);.
You can try fixing it in 2 ways:
If the receiving activity is from your own application, then try using explicit intent i.e Intent intent = new Intent("youCurrentClass","theClassYouWantToCall"); without feeding additional category, this will launch the specified activity. In case of explicit Intent Android system does not do a comparison with the intent-filters to match Intent Object.
Change the category section in relation to intent receiving Activity.
Hope this helps,
sku