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
Related
I have within an Activity, called CounterActivity, a counter that counts let's say from 100 down to 0 with a second interval. A DialogFrament is shown when the counter gets to 0 as follows:
MessageFragment dialog = new MessageFragment();
dialog.show(getSupportFragmentManager(), "MessageFragment");
The main layout of that activity has the following attribute set android:keepScreenOn="true",that way the screen will not timeout as long as the activity is visible. If I then open another application then onStop is called on CounterActivity. If the counter, which is still running in the background, gets to 0 instead of showing the DialogFragment the following exception is thrown:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
You cannot do fragment transactions when your activity is not on screen for UI reasons (your activity may be killed then restored, thus, any UI change won't be made again).
Therefore you must avoid any UI change when your activity is not active. You have multiple solutions to handle the problem :
1-You can simply register a boolean "showDialogOnResume", then override your "public void onResume()" :
#Override
public void onResume() {
super.onResume();
if(showDialogOnResume) {
/*build your dialog here*/
dialog.show(getSupportFragmentManager(), "MessageFragment");
}
}
If you are doing this in activity (not in fragment) i hevily recommand to do override "onPostResume()" instead. Look this post and especially jed answer and pjv comment.
It may even happen that you are not calling :
super.onActivityResult();
On your "onActivityResult()"; as Sufian said in his comment to jed answer.
Basically : avoid any UI change during activity lifecycle. Allow it only when your activity is active. If you cannot do that (other threads like AsyncTasks), get the answer, save it somehow, and perform your change on your activity result. Because if the user never resume your activity, you don't need to do your changes.
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!
I started using DialogFragment, because they are working nicely through orientation changes, and stuff. But there is nasty problem I encountered.
I have AsyncTask that shows progress DialogFragment and dismisses it onPostExecute. Everything works fine, except when onPostExecute happens while application is in background (after pressing Home button, for example). Then I got this error on DialogFragment dismissing - "Can not perform this action after onSaveInstanceState". Doh. Regular dialogs works just fine. But not FragmentDialog.
So I wonder, what is the proper way of dismissing DialogFragment while application is in background? I haven't really worked with Fragments a lot, so I think that I'm just missing something.
DialogFragment has a method called dismissAllowingStateLoss()
This is what I did (df == dialogFragment):
Make sure that you call the dialog this way:
df.show(getFragmentManager(), "DialogFragment_FLAG");
When you want to dismis the dialog make this check:
if (df.isResumed()){
df.dismiss();
}
return;
Make sure that you have the following in the onResume() method of your fragment (not df)
#Override
public void onResume(){
Fragment f = getFragmentManager().findFragmentByTag("DialogFragment_FLAG");
if (f != null) {
DialogFragment df = (DialogFragment) f;
df.dismiss();
}
super.onResume();
}
This way, the dialog will be dismissed if it's visible.. if not visible the dialog is going to be dismisded next the fragment becomes visible (onResume)...
This is what I had to do to achieve what you want:
I have a Fragment activity on which i was showing a dialog fragment named fragment_RedemptionPayment which is globally declared at the top. The following code dismisses the DialogFragment if it was showing before the activity goes in background and comes back in foreground.
#Override
public void onResume() {
super.onResume();
if(fragment_RedemptionPayment.isVisible()){
fragment_RedemptionPayment.dismiss();
}
}
Another new way of checking the state before calling dismiss is this:
if(!dialog.isStateSaved){
dialog.dismiss()
} else {
//Change the UI to suit your functionality
}
In this way its is checked that state is saved or not, basically on pause and onSaveInstanceState has been called.
For Java you can use isStateSaved()
A solution that might work is setting Fragment.setRetainInstance(true) in your dialogfragment, but that's not the prettiest of fixes.
Sometimes I have noticed that I have to queue up my dialog actions to let the framework restore the state first. If you can get hold of the current Looper (Activity.getMainLooper()) and wrap that in a Handler you could try passing your dismissal to the back of the queue by posting a runnable on that queue.
I often end up using a separate fragment that it retaininstance(true) that has a ResultReceiver. So i pass on that result receiver to my jobs and handle callbacks in its onReceive (often as a router for other receivers). But that might be a bit more work than it is worth if you are using async tasks.
I'm having trouble putting this problem into searchable terms. I'm working on an Android application, and specifically the splash screen for my app. The app needs to fetch data from an external web service (a blocking function call), while it does this the user gets a nice title, image and progress bar. When the data arrives the user is redirected to the main menu. Its a simple screen, everything being defined in the xml layout file, my problem is that I just get a black screen for a few seconds and then the main menu. If I press back I get the splash screen with the progress bar spinning away happily.
Here is what I have so far:
public class SplashActivity extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
}
#Override
public void onStart(){
super.onStart();
DatabaseManager db = new DatabaseManager(this.getBaseContext());
db.fetchExternCatalog(); //doesnt return until data arrives
Intent intent = new Intent().setClass(this, MainMenuActivity.class);
startActivity(intent);
}
}
It seems the screen isnt actually drawn until the activity is running (after onCreate(), onStart(), etc). I thought onStart() would be the perfect place to put this, but apparently not.
So how do I draw everything on the screen and make my blocking function call after so the user actually sees the splash screen while the data is downloaded?
You're going to be locking up the UI thread which is why i believe you are seeing a black screen. Use an AsyncTask or create your own thread pool for DB operations.
As far as hitting the back button and seeing your old activity, You need to tell android not to store the activity in it's stack. This should help:
http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html
you need to use the ProgressDialog class to build the dialog, and then run the blocking method inside a thread.
I'll post an example in a minute (gotta get near a PC :p)
private void showSplash(){
progressDialog = ProgressDialog.show(this, "Hello! ima title", "Im the message you see.");
progressDialog.show();
Thread t = new Thread(new Runnable(){
public void run(){
// Put your blocking method here.
// You may need to build in a "hey, im done downloading" variable to get it to close down right
progressDialog.dismiss();
}
});
t.start();
}
I'm trying to adjust the brightness of my phone programmatically. I've got an Activity in my app which is translucent to do this, however users can't click through it to the activity/window beneath it. I kill this activity as soon as the brightness is set, however I want to do more work in this activity (such as gradual brightness adjustment) which requires some time, and I don't want the user tapping at their phone wondering why their actions aren't being registered.
So basically, I need to either create a mock Window which will successfully allow me to adjust screen brightness without being displayed, or work out how to make an Activity click-through. I'm not sure how to do either.
BTW, this is the code making the brightness adjustments in the Activity:
android.provider.Settings.System.putInt(getContentResolver(),
android.provider.Settings.System.SCREEN_BRIGHTNESS, Math.round(SOME_BRIGHTNESS * 255f));
Window window = getWindow();
window.getAttributes().screenBrightness = SOME_BRIGHTNESS;
window.setAttributes(window.getAttributes());
float sysBrightPer = getSystemBrightness(getApplicationContext());
new Thread() {
public void run() {
try {
sleep(BRIGHT_TIMEOUT);
} catch (InterruptedException e) {
e.printStackTrace();
}
finish();
}
}.start();
Any advice?
P.S. I found this app on the market. I wonder if the way this has been achieved would help me? https://market.android.com/details?id=com.haxor
Hah! That app did help me, if only because it led me to this solution!
Brightness Screen Filter
For the click lazy, use this:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
I'm afraid this no longer works in 4.0+, if applied to the window itself (presumably to the prevent use of activity class methods like onkey from a transparent overlay). However one can still use windowmanager.addview or layoutinflater.inflate to add a custom view class which extends viewgroup, and if you use layoutparams.FLAG_NOT_TOUCHABLE in adding or inflating this view, it will be click-through, and remain on top even when the activity that called it goes into onpause.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
If you want to intercept touches on specific views you can use the window manager to add a view with different flags:
e.g.
WindowManager.LayoutParams params = new WindowManager.LayoutParams(...);
getWindowManager().addView(myButton,params);