I have an Activity that I want to run a Delay Function when it runs. I [i]don't[/i] want a delay in OnClick function, I want delay when activity [i]starts[/i].
I have tried the following solutions :
How to set delay in Android onClick function
How to pause/delay on Android?
Android: Timer/Delay Alternative
Android timer set delay
...and some more and none of them did what I want. I want a delay when activity starts (for my project , when The Game Starts) but with that codes, it starts the delay (e.g 10s) when I put my finger on the screen.
You should put a Thread.sleep(long) before the "setContentView(R.layout.xxxx..)" in the onCreate(..) function. In that way, it will actually delay before showing you the elements of the Activity.
If you want to delay even before the onCreate(...) is fired, the approach will need to be different, here is one suggestion:
Run a Service and check for the Foreground application using ActivityManager class (see sample code below). Keep checking for when your app is fired or brought to the 'foreground' (using code below) and then just go back to homescreen & start a timer (in the service itself). Once the timer expires, start your app.
You can run the function below inside an AsyncTask in the Service.
The two approaches are quite different and really depends on what you are looking to achieve exactly.
#SuppressWarnings("deprecation")
private void getRunningAppName() throws NameNotFoundException {
Log.v("neiltag", "Entered getRunningAppName()");
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
// The first in the list of RunningTasks is always the foreground task.
RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();
PackageManager pm = this.getPackageManager();
PackageInfo foregroundAppPackageInfo = pm.getPackageInfo(foregroundTaskPackageName, 0);
String foregroundTaskAppName = foregroundAppPackageInfo.applicationInfo.loadLabel(pm).toString();
String packageName = foregroundAppPackageInfo.packageName;
if(foregroundTaskAppName.matches("<NAME OF YOUR APP HERE>")) {
//If your app is fired go back to the Homescreen(i.e. the delay)
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "You are not allowed to open Facbeook now, sorry!", Toast.LENGTH_SHORT).show();
}
});
}
//ADD A TIMER HERE
//ONCE TIMER EXPIRES, FIRE UP YOUR APP AGAIN
}
Related
I am just starting to learn Android, Java and need help.
I have an activity with the countdowntimer, which works fine. However, I want it to be displayed in the fragment. What is the best way to do it?
I tried calling Timer.getCountdowntimer, I tried calling Timer.getUserTime (userTime is the user selected time for the countdowntimer), but the textview in my fragment doesn't display the timer.
thanks in advance!
If you are coding in Java purely, and want to use the android SDK to do it, I would recommend:-
//Create a handler that runs on main loop so we can update UX
final android.os.Handler handler = new android.os.Handler(Looper.getMainLooper());
//Get a callback in 1 second
handler.postDelayed(new Runnable() {
int timer;
#Override
public void run() {
timer += 1;
myTextView.setText(String.valueOf(timer));
//Recursively get another callback in a second
handler.postDelayed(this, 1000);
}
}, 1000);
Make sure you add some logic to stop the timer when you want, and also onPause/onResume
I am writing my code in Android Studio, but the project that I am writing has no GUI, and never updates views for a user. It simply listens for the last installed app with a Broadcast Receiver and sends info to another java file.
I am wondering how I can send a string from a broadcast receiver to an activity (maybe this should not be an "activity" but a "service"?), and have this work while the app is in the background.
Right now I have a broadcast receiver listening for the last installed app on my phone (this runs in the background). And I have a custom broadcast receiver set up to notify my main activity when the broadcast receiver gets an installed app. But this custom receiver doesn't work in the background. Again, maybe I shouldn't be using an Activity to receive info from the BroadcastReceiver?
Is there a way I can send information from my broadcast receiver to my main activity while the app is in the background? I also need my main activity to resume normal function while in the background (there are no GUI updates done while it's in the background).
My BroadcastReceiver which is sending data to my Main Activity through a new Intent
public class NewInstallReceiver extends BroadcastReceiver {
ApplicationInfo ai;
#Override
public void onReceive(Context context, Intent intent) {
final PackageManager pm = context.getPackageManager();
try {
// if app is added, get package info
ai = pm.getApplicationInfo(intent.getData().getSchemeSpecificPart(), 0);
Intent i = new Intent("broadcastName");
// Data pass to activity
i.putExtra("appInfo", ai);
context.sendBroadcast(i);
} catch (final PackageManager.NameNotFoundException e) {
ai = null;
}
}
}
In my MainActivity in onCreate I register the receiver:
registerReceiver(broadcastReceiver, new IntentFilter("broadcastName"));
I receive data from BroadcastReceiver
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// get applicationInfo
Bundle b = intent.getExtras();
Object applicationInfo = b.get("appInfo");
ApplicationInfo appInfo = (ApplicationInfo) applicationInfo;
getNewData(appInfo);
}
};
Then I have to unregister the receiver in MainActivity, but obviously this doesn't allow for me to receive info from BroadcastReceiver once the app goes in the background
#Override
public void onStop()
{
try{
unregisterReceiver(broadcastReceiver);
}
catch(Exception e){
System.out.println("Exception is " + e.toString());
}
super.onStop();
}
Honestly, I don't think that update an Activity that is in background is a good practice (even if possible).
According to DOCS:
An activity is a single, focused thing that the user can do. Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI with setContentView(View). While activities are often presented to the user as full-screen windows, they can also be used in other ways: as floating windows... or embedded inside of another activity (using ActivityGroup).
So, if the Activity is in background, it does not visible. So, it is useless to update its contents (because it is not visible to user).
In fact, you should implement following behavior instead:
Use your Service only to save the information (in a database/content provider) and to notifies the Activity that a new information is available. Then, if your activity is open, it immediately consumes that information. If Activity is not opened, the info remains saved for when the user needed it.
If app was only stopped, you can update the Activity content during onResume() method.
If your app was killed and user opened it again, you can update ALL Views during onCreate() method. onCreate() is called before the View is displayed to user.
This way, the info will be updated when needed: when the user wan's to check the info. Otherwise, it is a waste of time.
I have an app with a title screen. When the app first starts, I have an onCreate method that contains the following code:
setContentView(R.layout.title_screen);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
setContentView(R.layout.main_screen);
}
}, 2000);
When I run my app and press the back button while on the main_screen layout, it closes the app (as it should). However, when I reopen the app, it displays the title_screen layout for two seconds again even though the app is already running. How can I prevent this?
This will prevent the delay appearing again when resumed:
private static boolean flag = false;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!flag){
setContentView(R.layout.title_screen);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
setContentView(R.layout.main_screen);
}
}, 2000);
flag = true;
} else {
setContentView(R.layout.main_screen);
}
}
Btw, if your app was on background and it is calling onCreate again while being resumed, it means that it is killed by the OS. Therefore it is normal to have the initial delay again.
What I would do is to implement two different activities first one showing title_screen and the second which is started after 2s should show your main screen.
After looking at your code I can see that you ALWAYS start with title_screen then after 2s, you change to main_screen. Therefore, when you press back, that means you finish your activity. When you re-open your app, onCreated is called again, and it run every line of code as the previous opening.Of course, there's no difference in 2 times you open your app. To overcome it, I recommend to use SharedPreference to store the flag to check main_screen or title_screen.
My issue is that upon opening a certain activity in my project, I initialize a ScheduledExecutorService that sends an Intent to an IntentService class every 20 seconds.
Now when I first open the activity that contains the ScheduledExecutorService, the Intent fires once every 20 seconds as planned.
The issue arises when I exit the activity (staying in the app) and then reenter the activity. This results in the Intent being sent twice in a 20 second window, and I figure it has to do with my creating a new ScheduledExecutorService in the onResume of my activity.
How do I ensure that there is only one instance of ScheduledExecutorService at any given time?
Relevant code is below:
#Override
public void onResume() {
super.onResume();
ScheduledExecutorService scheduleIntentSender = Executors.newScheduledThreadPool(1);
scheduleIntentSender.scheduleAtFixedRate(new Runnable() {
public void run() {
sendIntent();
}
}, 0, 20,TimeUnit.SECONDS);
mDownloadStateReceiver =
new DownloadStateReceiver();
// Registers the DownloadStateReceiver and its intent filters
LocalBroadcastManager.getInstance(this).registerReceiver(
mDownloadStateReceiver,
testIntentFilter);
}
I suggest not doing that in your Activity because it's intended to display a UI. Do that in a Service instead. You can launch a Service in onStart and track the state of the executor in your Service, whether it's launched or not. Service is good because it's a background component which is not tied to UI at all. It will not be affected during screen rotations etc.
You should cancel the previous ScheduledExecutorService after closing activity:
ScheduledExecutorService scheduleIntentSender = Executors.newScheduledThreadPool(1);
final ScheduledFuture schedulHandler = scheduleIntentSender.scheduleAtFixedRate(new Runnable() {
public void run() {
sendIntent();
}
}, 0, 20,TimeUnit.SECONDS);
//Call schedulHandler.cancel(true) to cancel scheduleIntentSender in onDestroy()
I have some problems with starting new activity. In my app I have setup broadcast receiver which listens for intent (screen off). When screen is off, my app should start new activity (under certain conditions of course. I'm not making spam app). But sometimes it isn't.
I have declared that activity "singleTop" in my manifest, so I override "onNewIntent" method also.(I think it's important to tell this) But here is the thing.
When phone goes to sleep and if certain conditions are met, then 2 icons appear on the screen (My activity). I made those icons clickable, and if I click my second icon I'm FINISHING (finish()) current activity and I'm starting new CALL LOG activity (owned by Android). When I do that, it should bring back previous activity (with different layout - only one icon - previous displayed together with second one), but again only if phone goes to sleep. The thing is that it doesn't. According to my LOGCAT, all conditions are met but only activity is not started. What is happening with my activity lifecyle here?
Screen Off Receiver code:
#Override
public void onReceive(Context context, Intent intent) {
Log.d("APP", "MAINSERVICE, Screen OFF");
MissedCallObserver mco = new MissedCallObserver(MainService.this);
if(!CallListener.isCallActive) {
Log.d("APP", "MAINSERVICE, INSIDE IF ( call is not active )");
if(mco.checkMissedCalls() > 0 || mco.checkUnreadSms() > 0) {
Log.d("APP", "MAINSERVICE, calls calculated. IF entered. Next is starting activity");
startHandleActivity();
}
}
} // outer if
} // ScreenOffReceiver
private void startHandleActivity() {
Intent startH_Activity = new Intent(MainService.this, HandleActivity.class);
startH_Activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startH_Activity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(startH_Activity);
}
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
wl.acquire();
This will allow to execute code reliably after the Screen Off Intent fires.