Android: Crouton + Activities state - android

I'm using Crouton im my project.In app i have few activities.
In sub activities i want do some operations after finishing a process i make redirect to main activity and display Crouton message about result in previous activity.
But hier i have problems...Crouton closes quickly after redirect. I found some solution:
1) Create intent for sub activity
2) close main activity
3) start sub activity
do some work...
4) Create intent for main activity
5) Put info in extra about changes
5) open main activity
and in main activity, in onCreate, i trying get extra about changes. I tried get info from extra in onStart, onResume..but still the same..Crouton message closes quickly, faster than needed.
What i am doing wrong?
Maybe my algorithm with displaying Crouton is wrong..Pls correct me.
Thx a lot!

You have two options:
1) You can open your second activity with startActivityForResult() and than handle the result in your MainActivity to show the crouton. In the Android docs you can find a good tutorial for it: Android developer After ending the second activity you handle the result code and show the right text.
2) You can send it as you mentioned in a Extra with startActivity() and pass the in the intent:
start activity
Hope it helps!

I found solution to my question:
#Override
protected void onResume() {
super.onResume();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
displayEvents();
}
}, 500);
}
private void displayEvents(){
//Проверяю какое уведомление необходимо показать
if(intent.hasExtra("event")){
if(intent.hasExtra("event") && intent.getStringExtra("eventType").equals("confirm")) {
Crouton.makeText(MainActivity.this, intent.getStringExtra("event"), Style.CONFIRM).show();
getIntent().removeExtra("event");
getIntent().removeExtra("eventType");
}
}
}
done!

Related

How to make rest of methods start after new intent activity is finished

I call new activity from one function like below.
I want to make loadRoundFromExercise() ~ updateRound() methods starts after new activity called from openRegisterPopupActivity() is finished
I thought to put sleep method. but I can't estimate how long user are going to put text.
So.. how can I fix this? plz help me.
Thank you.
adapter.setRoutineListener(new HealthRoutineViewHolder.Listener() {
#Override
public void onAddItem(ExerciseLog exerciseLog) {
setupLogReference(exerciseLog);
openRegisterPopupActivity(); // I call new activity here by intent.
loadRoundFromExercise();
convertToRoundLog();
updateRound();
}
You could use startActivityForResult() and the onActivityResult() callback. These basically let Activity A start Activity B and then return a result back to Activity A.
Use onactivityresult android

Show a view on top of all activities

I have a service running in background and when some conditions are met I need to show a window at the top of the activity. I should be able to navigate between activities and that window should always stay static on top till the user dismiss it.
Options:
I tried with an activity using Dialog Theme. The problem with this approach is that it will be on top of the activity that was at that instant. If I open another activity the "activity dialog" will be behind this new activity.
I thought to implement a BaseActivity that has a frame layout in order to show this "window" every time you open a new Activity. The problem is that is being show again and it shouldn't, the window should be static meanwhile the activities are changing. Also not sure how to call transaction manager inside a service to add the fragment.
I read something about having a Service that will attach a View on the Window Manager. The problem with this is that I am not sure if it's a good practice.
Any thoughts? Thanks!
I have one solution for that
1. create a static variable in app
public static Boolean isMatch=false ;
2. either create dialog or layout that you have to show in activity and manage its show and hide.
2. Create Thread in activity and add 1000 timer
Thread thread= new Thread() {
int wait = 0;
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void run() {
super.run();
while (wait < welcomeScreenDisplay) {
sleep(100);
if(isMatch)
{
dialog.show();
}
wait += 100;
}
}//run
};//welcome thread
t.start();
3. in service when the condition is true update the value of the variable
isMatch =true ;
you can send a declare an explicit broadcast receiver for your app and once the service is done then automatically will send a message to the parent activity. In this activity you will have a view at the top with visibility gone, and once you receive the broadcast change the visibility

Android In App Billing Access from another activity

I have all the In App Billing code working fine on my MainActivity.
The problem is that I want to access that code from another activity.
The code I'm trying to reach is here on my main Activity:
public void buyCode() {
Log.d(TAG, "2. Button pressed");
mHelper.launchPurchaseFlow(MainActivity.this, SKU_TEST, 10001,
mPurchaseFinishedListener, "abc123abc1234");
}
I've tried using this code on my OnClickListener on the Other Activity but it's not working, result NullPointerException
MainActivity myMainActivity = new MainActivity();
myMainActivity.buyCode();
How can I accomplish this?
Thanks
You cannot create an instance of activity by yourself and expect it behaving as a activity created by system. It won't work because system handles all the lifecycle events like create, start, stop, pause etc.
You either need to have a dedicated activity for in-app payments or you need to embed mHelper into every activity to execute buying (which is less preferable).
In the first case your main activity must be only responsible for buying operations and handling results. Then you can call it via Intent from any other activity. In the second case you implement same buying logic in multiple activities (which is bad idea) and you don't need to call main activity any longer.
If, in your case, main activity does more, than just handling in-app payments, then you can call it with an additional flag, saying a user want to buy something. You can do it as following.
// calling activity
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("purchase", true);
startActivity(intent);
// MainActivity.java
#Override
public void onCreate(Bundle savedInstanceState) {
boolean executePurchase = getIntent().getBooleanExtra("purchase", false);
if (executePurchase) {
// start purchasing logic
...
} else {
// continue with the standard logic
...
}
}
But the MainActivity will be started in front of calling activity, and you cannot avoid this with the design you currently have.

Android Launching the current activity with different Intent Action

[Update Solution]
Referring to the post in the link
ViewPager PagerAdapter not updating the View
public void onSomeButtonClicked(View view) { // registered to Button's android:onClick in the layout xml file
Log.w(TAG,"Some button clicked !!");
getIntent().setAction(IntentManager.Intents.ACTION_SPAWN_LIST_BY_SOMETHING);
mViewPager.getAdapter().notifyDataSetChanged();
}
// And inside my PagerAdapter
#Override
public int getItemPosition(Object object) {
return 0;
}
Fixed all my problems, i just used Intent.setAction().
[Update to below Post]
My problem is i have a ViewPager PagerAdapter in my Main Activity. On clicking one of the 3 buttons., any specific intent will be fired (i used intent, i could have gone with just State variable as well, just that i pass some Uri with the intent). What happens is., i do
public void onSomeButtonClicked(View view) { // registered to Button's android:onClick in the layout xml file
Log.w(TAG,"Some button clicked !!");
getIntent().setAction(IntentManager.Intents.ACTION_SPAWN_LIST_BY_SOMETHING);
mViewPager.getAdapter().notifyDataSetChanged();
}
This is why i was guessing maybe i should just do startActivity again, with the new Intent Action on the same Activity.
Spawning a new Activity, i would have to redraw every other view in the layout which is basically the same code, for the most part in the current activity.
Any suggestions here? Please help
[Original Post]
I have a PagerAdapter and 3 Buttons in the my Main Activity. This activity is enter from Main Launcher.
When i press any one of the buttons, the Intent Action is changed.
My question:
The changed Intent action reflects some changed view in the ViewPager and does_not spawn a new Activity as such, only the view is updated.
What approach should i take to get this task?
Can i start the currentActivity using startActivity() and different Intent actions on button click?
or is there any other efficient way in android to do this?
[No need code, just explanation of logic / method would suffice]
Thanks in advance
If you are saying that you are trying to use startActivity to bring up the same activity again, and its not working, it could be because you set something like singleTop in your Android manifest.
If you are asking whether or not you should use an intent to change the state of your Activity, then the answer is "it depends". If the user would expect the back button to return your app to its previous state (instead of going back to the home screen), then it might be a good choice for you. If that is the case, however, I would ask why not just make 2 different Activities? Otherwise, just do as Dan S suggested and update the state of your Activity as the user interacts with it.
You can always use the onNewIntent() hook. Do something like this in your activity:
protected void onNewIntent(Intent intent){
//change your activity based on the new intent
}
Make sure to set the activity to singleTop in your manifest. Now whenever startActivity is called the onNewIntent() will be executed. Also, note that per the documentation:
Note that getIntent() still returns the original Intent. You can use setIntent(Intent) to update it to this new Intent.

How to check if an activity is the last one in the activity stack for an application?

I want to know if user would return to the home screen if he exit the current activity.
I'm going to improve on the comment of #H9kDroid as the best answer here for people that have a similar question. (Original link)
You can use isTaskRoot() to know whether the activity is the root of a task.
UPDATE (Jul 2015):
Since getRunningTasks() get deprecated, from API 21 it's better to follow raukodraug answer or Ed Burnette one (I would prefer second one).
There's possibility to check current tasks and their stack using ActivityManager.
So, to determine if an activity is the last one:
request android.permission.GET_TASKS permissions in the manifest.
Use the following code:
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
if(taskList.get(0).numActivities == 1 &&
taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
Log.i(TAG, "This is last activity in the stack");
}
Please note, that above code will be valid only if You have single task. If there's possibility that number of tasks will exist for Your application - You'll need to check other taskList elements. Read more about tasks Tasks and Back Stack
Hope this will help new beginners, Based above answers which works for me fine, i am also sharing code snippet so it will be easy to implement.
solution : i used isTaskRoot() which return true if current activity is only activity in your stack and other than i also handle case in which if i have some activity in stack go to last activity in stack instead of opening new custom one.
In your activity
#Override
public void onBackPressed() {
if(isTaskRoot()){
startActivity(new Intent(currentActivityName.this,ActivityNameYouWantToOpen.class));
// using finish() is optional, use it if you do not want to keep currentActivity in stack
finish();
}else{
super.onBackPressed();
}
}
there is an easiest solution to this, you can use isTaskRoot()
in your activity
One way to keep track of this is to include a marker when you start a new activity and check if the marker exists.
Whenever you start a new activity, insert the marker:
newIntent=new Intent(this, NextOne.class);
newIntent.putExtra(this.getPackageName()+"myself", 0);
startActivity(newIntent);
And you can then check for it like this:
boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")
While there may be a way to achieve this (see other answers) I would suggest that you shouldn't do that. Normal Android applications shouldn't need to know if the Home screen is about to display or not.
If you're trying to save data, put the data saving code in your onPause() method. If you're trying to give the user a way to change their mind about existing the application, you could intercept the key up/down for the Back key and the onBackPressed() method and present them with an "Are you sure?" prompt.
I've created a base class for all my activities, extending the AppCompatActivity, and which has a static counter:
public abstract class BasicActivity extends AppCompatActivity {
private static int activityCounter = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
++activityCounter;
...
}
#Override
public void onDestroy() {
super.onDestroy();
--activityCounter;
if(activityCounter==0) {
// Last instance code...
}
}
public boolean isLastInstance() { return (activityCounter==1); }
}
This has worked well enough, so far; and regardless of API version. It requires of course that all activities extends this base class - which they do, in my case.
Edit: I've noticed one instance when the counter goes down to zero before the app completely exits, which is when the orientation is changed and only one activity is open. When the orientation changes, the activity is closed and another is created, so onDestroyed is called for the last activity, and then onCreate is called when the same activity is created with the changed orientation. This behaviour must be accounted for; OrientationEventListener could possibly be used.
The Problem with sandrstar's solution using ActivityManager is: you need a permission to get the tasks this way.
I found a better way:
getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
The Activity on the Stack bottom should allways get this category by default while other Activities should not get it.
But even if this fails on some devices you can set it while starting your Activity:
Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);
Android implements an Activity stack, I suggest you read about it here. It looks like all you want to do though is retrieve the calling activity: getCallingActivity(). If the current activity is the first activity in your application and the application was launched from the home screen it should (I assume) return null.
The one thing that missed here, is the "Home key" click, when activated, you can't detect this from your activity, so it would better to control activity stack programmatically with handling "Back key" press and moving to required activity or just doing necessary steps.
In addition, you can't be sure, that starting your activity from "Recent Activity" list can be detected with presetting some extra data into intent for opening activity, as it being reused in that case.

Categories

Resources