I'm developing an Android app.
The app should show a Splash Screen at startup while checking if a file is updated. If the file is not updated, it launches an Async Task to update the file.
The problem is, the image of the Splash Screen only shows when the file actually needs updating. Else, a black screen shows while performing the check.
My SplashScreen activity:
public class SplashActivity extends Activity
{
private final static String placesFile = "places";
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_splash);
}
#Override
protected void onResume()
{
super.onResume();
if(!isFileUpdated()){
new PlacesService(this).execute();
}else{
intentAndFinish();
}
}
private void intentAndFinish() {
finish();
Intent mainIntent = new Intent(this, MainActivity.class);
startActivity(mainIntent);
}
/**
*
* #return false if Places Data is too old
*/
private boolean isFileUpdated() {
int daysOld = 0;
File f = new File(this.getFilesDir().getAbsolutePath() +"/"+placesFile);
if(f.exists()){
System.out.println("existe");
}
Date d = new Date();
Date currentDate = new Date(System.currentTimeMillis());
d.setTime(f.lastModified());
if(currentDate.compareTo(d)>0)
daysOld = determineDifferenceInDays(d, currentDate);
return daysOld < Consts.PLACES_DAYS_OLD_QTY_PERMITTED?true:false;
}
private static int determineDifferenceInDays(Date date1, Date date2) {
Calendar calendar1 = Calendar.getInstance();
calendar1.setTime(date1);
Calendar calendar2 = Calendar.getInstance();
calendar2.setTime(date2);
long diffInMillis = calendar2.getTimeInMillis() - calendar1.getTimeInMillis();
return (int) (diffInMillis / (24* 1000 * 60 * 60));
}
public void onResultFromAsyncTask(boolean finished) {
if(finished){
intentAndFinish();
}
}
}
activity_splash.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:src="#drawable/splash_es"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
You are killing your Splash before it be on the Screen. Because you are killing it inside the onResume method. Look this piece of documentation:
The foreground lifetime of an activity happens between a call to onResume() until a corresponding call to onPause(). During this time the activity is in front of all other activities and interacting with the user. An activity can frequently go between the resumed and paused states -- for example when the device goes to sleep, when an activity result is delivered, when a new intent is delivered -- so the code in these methods should be fairly lightweight.
You can use a handler, it is more elegant than Thread to solve this problem, but the main ideia is the same of #sheetal.
On onCreate method:
handler = new Handler();
On onResume method:
handler.postDelayed(new Runnable() {
public void run() {
if(!isFileUpdated()){
new PlacesService(this).execute();
}else{
intentAndFinish();
}
}
}, 1000);
If your file is updated You are closing your activity in onResume and switching to main activity and the process will take fraction of milliseconds to do that..so it is very much possible you will never see your spash screen..If you want you can use
private void intentAndFinish() {
Thread.sleep(10000)
finish();
Intent mainIntent = new Intent(this, MainActivity.class);
startActivity(mainIntent);
}
Just to catch up with your splashScreen.
See #bruno 's post...We should use a handler
You call to isFileUpdated() takes time put it in background
You asyntask should be something like this
public class PlacesService extends Asynctask<Void,Void,Void>{
boolean flag=false
public Void doInBackground(){
flag=isFileUpdated()
if (!flag){
return
}else {
// Do your file update
}
return
}
public onPostExcecute(){
intentAndFinish();
}
}
Related
I have an assignment of moving the png file of a signature to one of our servers. The solution I implemented is to have a background service that monitors the folder it is saved in then move it. This works well but the service shuts down after a certain period of time, might be an hour or something, but I'd like it to be persistent. Doing some research resulted in either using a alarm manager or a handler to keep the activity alive.
I decided to use the handler. However whenever the activity is called the device hangs and it takes more memory every time I refresh it. The culprit may be due to not calling 'stopWatching()' though it is possible I handled the problem incorrectly.
SendToPHP.java
public class SendToPHP extends Activity {
final int FIFTEEN_MINUTES_IN_MILLISECONDS = 900000;
//The handler will run the function restart at a later time
//This should prevent the intent service timeout.
Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
finish();
startActivity(getIntent());
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent mServiceIntent = new Intent(SendToPHP.this,
BackgroundService.class);
// Starts the IntentService
SendToPHP.this.startService(mServiceIntent);
handler.postDelayed(runnable, FIFTEEN_MINUTES_IN_MILLISECONDS);
}
}
BackgroundService.java
#Override
protected void onHandleIntent(Intent workIntent) {
/************* Php script path ****************/
upLoadServerUri = "*redacted*";
//FileObserver monitors files/directories, in this case we want any file that is
//created in SignItPictures
FileObserver observer = new FileObserver(android.os.Environment
.getExternalStorageDirectory().toString() + "/Pictures/SignItPictures", FileObserver.CREATE ) {
#Override
public void onEvent(int event, String file) {
uploadFileName = file;
uploadFile(uploadFilePath + "/" + uploadFileName);
}
};
observer.startWatching(); // start the observer
}
Try adding START_STICKY in the onStartCommand method of your Service class
My app is loading the start page in 10 seconds. In that time of 10 sec android screen is blank.
In that time I want to add the loading screen. How to add it?
And tell me in app how to know the starting page is loading? And tell me how to do in my app?
use ProgressDialog.
ProgressDialog dialog=new ProgressDialog(context);
dialog.setMessage("message");
dialog.setCancelable(false);
dialog.setInverseBackgroundForced(false);
dialog.show();
hide it whenever your UI is ready with data. call :
dialog.hide();
You can use splash screen in your first loading Activity like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
Thread welcomeThread = new Thread() {
#Override
public void run() {
try {
super.run();
sleep(10000); //Delay of 10 seconds
} catch (Exception e) {
} finally {
Intent i = new Intent(SplashActivity.this,
MainActivity.class);
startActivity(i);
finish();
}
}
};
welcomeThread.start();
}
Hope this code helps you.
Please read this article
Chris Stewart wrote there:
Splash screens just waste your time, right? As an Android developer,
when I see a splash screen, I know that some poor dev had to add a
three-second delay to the code.
Then, I have to stare at some picture for three seconds until I can
use the app. And I have to do this every time it’s launched. I know
which app I opened. I know what it does. Just let me use it!
Splash Screens the Right Way
I believe that Google isn’t contradicting itself; the old advice and
the new stand together. (That said, it’s still not a good idea to use
a splash screen that wastes a user’s time. Please don’t do that.)
However, Android apps do take some amount of time to start up,
especially on a cold start. There is a delay there that you may not be
able to avoid. Instead of leaving a blank screen during this time, why
not show the user something nice? This is the approach Google is
advocating. Don’t waste the user’s time, but don’t show them a blank,
unconfigured section of the app the first time they launch it, either.
If you look at recent updates to Google apps, you’ll see appropriate
uses of the splash screen. Take a look at the YouTube app, for
example.
You can create a custom loading screen instead of splash screen. if you show a splash screen for 10 sec, it's not a good idea for user experience. So it's better to add a custom loading screen. For a custom loading screen you may need some different images to make that feel like a gif. after that add the images in the res folder and make a class like this :-
public class LoadingScreen {private ImageView loading;
LoadingScreen(ImageView loading) {
this.loading = loading;
}
public void setLoadScreen(){
final Integer[] loadingImages = {R.mipmap.loading_1, R.mipmap.loading_2, R.mipmap.loading_3, R.mipmap.loading_4};
final Handler loadingHandler = new Handler();
Runnable runnable = new Runnable() {
int loadingImgIndex = 0;
public void run() {
loading.setImageResource(loadingImages[loadingImgIndex]);
loadingImgIndex++;
if (loadingImgIndex >= loadingImages.length)
loadingImgIndex = 0;
loadingHandler.postDelayed(this, 500);
}
};
loadingHandler.postDelayed(runnable, 500);
}}
In your MainActivity, you can pass a to the LoadingScreen class like this :-
private ImageView loadingImage;
Don't forget to add an ImageView in activity_main.
After that call the LoadingScreen class like this;
LoadingScreen loadingscreen = new LoadingScreen(loadingImage);
loadingscreen.setLoadScreen();
I hope this will help you
public class Splash extends Activity {
private final int SPLASH_DISPLAY_LENGHT = 3000; //set your time here......
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
/* Create an Intent that will start the Menu-Activity. */
Intent mainIntent = new Intent(Splash.this,MainActivity.class);
Splash.this.startActivity(mainIntent);
Splash.this.finish();
}
}, SPLASH_DISPLAY_LENGHT);
}
}
If the application is not doing anything in that 10 seconds, this will form a bad design only to make the user wait for 10 seconds doing nothing.
If there is something going on in that, or if you wish to implement 10 seconds delay splash screen,Here is the Code :
ProgressDialog pd;
pd = ProgressDialog.show(this,"Please Wait...", "Loading Application..", false, true);
pd.setCanceledOnTouchOutside(false);
Thread t = new Thread()
{
#Override
public void run()
{
try
{
sleep(10000) //Delay of 10 seconds
}
catch (Exception e) {}
handler.sendEmptyMessage(0);
}
} ;
t.start();
//Handles the thread result of the Backup being executed.
private Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
pd.dismiss();
//Start the Next Activity here...
}
};
Write the code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
Thread welcomeThread = new Thread() {
#Override
public void run() {
try {
super.run();
sleep(10000) //Delay of 10 seconds
} catch (Exception e) {
} finally {
Intent i = new Intent(SplashActivity.this,
MainActivity.class);
startActivity(i);
finish();
}
}
};
welcomeThread.start();
}
I have an activity in which i need to implement a basic mm::ss timer . Below is the code i have written for it. However the problem is that when i press the back button in the emulator and click on the app again, the values change much faster. It looks like the onCreate is being called again. How do i rectify this?
I have tried creating a boolean variable and setting it to true the first time the task is invoked . I call the startPeriodidUpdates() only when the value is false.But the onCreate creates the variable again with the value of false.
public class GraphicsActivity extends Activity {
static int seconds = 0;
static int minutes = 0;
public static String time_elapsed;
public static boolean clearView = true;
Handler myhandler = new Handler();
public static String min,sec;
public static boolean running = true;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startPeriodicUpdates();
}
public void onResume(){
super.onResume();
}
public void onPause() {
super.onPause();
}
public void onStop(){
super.onStop();
}
public void startPeriodicUpdates()
{
periodicCall();
}
public void stopPeriodicUpdates(){
myhandler.removeCallbacksAndMessages(myhandler);
}
public void periodicCall()
{
seconds++;
if(seconds ==60)
{
seconds=0;
minutes++;
if(minutes==60)
{
seconds=0;
minutes=0;
}
}
// left-padding zeros to the minutes and seconds values
min = String.format("%02d",minutes);
sec = String.format("%02d",seconds);
time_elapsed = min + ":" + sec;
time_elapsed = min + ":" + sec + "";
myhandler.postDelayed(new Runnable(){
public void run(){
periodicCall();
}
},1000);
}
Perhaps this will help: The right way to do a peridic task is registering the handler in the OnResume and unregister in in OnPause. (You can unregister it other places, but OnPause is important)
I think its better if you use a Service for implementing your timer. Even if you push back button, the Service will continue running.
Here you can see a question I asked a bit time ago. You can see the implementation of a Custom Chronometer using a Service.
The activity where you want to receive the value of the Chronometer just need to have a BroadcastReceiver like:
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
mMilis = intent.getLongExtra("milis",0);
String time = intent.getStringExtra("tiempo");
// Do Something with the time
}
};
This may not be a solution to the problem above, but if you just want to update a view and count up form a given time, maybe have a look at Chronometer. If you want to count down and update views, you can do that with CountDownTimer
You can use shared preference to use this method only once .
//pass true first time
protected void storeSharedPrefs(Boolean value) {
/*
* Storing in Shared Preferences
*/
editor.putString("first", value);
editor.commit(); //Commiting changes
}
Check each on time application is loaded, whether its the first time and configuration details has been entered correctly by checking SharedPreferences
private boolean first_time_check() {
/*
* Checking Shared Preferences if the user had pressed
* */
Boolean first = uPreferences.getString("first", false);
return first;
}
I wrote a splash screen. But the problem is as the splash screen shown in the screen a keyboard also invoked. What could be the possible reason for this??
Please find the image below
and the code gos as below for the activity
public class SplashActivity extends Activity{
private final int SPLASH_DISPLAY_LENGHT = 2000;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
/* New Handler to start the Menu-Activity
* and close this Splash-Screen after some seconds.*/
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
/* Create an Intent that will start the Menu-Activity. */
Intent splash2 = new Intent(SplashActivity.this,SplashActivityRed.class);
SplashActivity.this.startActivity(splash2);
SplashActivity.this.finish();
overridePendingTransition(R.anim.fadein,R.anim.fadeout);
}
}, SPLASH_DISPLAY_LENGHT);
}
}
and the xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:id="#+id/imageViewSplash" android:layout_height="fill_parent" android:layout_width="fill_parent" android:background="#drawable/splash1" android:src="#drawable/splash1"></ImageView>
</LinearLayout>
PS: Sorry I had to hide the text and logo as they come under non-disclosure policy of the company I work for.
Please Remove the imageView from the Layout and add the following line the Linear Layout element
android:background="#drawable/splash1"
Like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background:"#drawable/splash1">
</LinearLayout>
Hope this helps
Also Change the implementation of the SplashScreen with above layout. To change the time line change the value of welcomeScreenDisplay to wotever you want. Currently it is 4 seconds i.e. 4000 mili seconds.
public class SplashScreen extends Activity {
String status, subscriber;
Intent i = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("FIRST");
setContentView(R.layout.splash);
System.out.println("in HOME SCREEN");
/** set time to splash out */
final int welcomeScreenDisplay = 4000;
/** create a thread to show splash up to splash time */
Thread welcomeThread = new Thread() {
int wait = 0;
#Override
public void run() {
try {
super.run();
/**
* use while to get the splash time. Use sleep() to increase
* the wait variable for every 100L.
*/
while (wait < welcomeScreenDisplay) {
sleep(100);
wait += 100;
}
} catch (Exception e) {
System.out.println("EXc=" + e);
} finally {
/**
* Called after splash times up. Do some action after splash
* times up. Here we moved to another main activity class
*/
finish();
}
}
};
welcomeThread.start();
}
}
Use this method:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
probably you need to disable the touch event for image. However as remove the imageView from the Layout and add background image to the linear layout element
android:background="#drawable/splash1"
I'm trying to show an alert dialog with my application from a non-activity.
So the hard thing here is that I want to do it not in an activity but in my general application class.
public class AppName extends com.github.droidfu.DroidFuApplication {
public static long TIME_CONTENT_UPDATE = 60; //half hour
Handler mHandler = new Handler();
#Override
public void onCreate() {
super.onCreate();
intent = new Intent(this, VSSyncController.class);
setupTimer();
}
private void setupCatalogTimer() {
final Context con = this;
//A handler runs on a separate thread
mHandler = new Handler(new Handler.Callback() {
public boolean handleMessage(Message msg) {
showMyAlertDialog(con)
mHandler.sendEmptyMessageDelayed(0, TIME_CONTENT_UPDATE);
return true;
}
});
}
}
Basically I want to show an alert dialog from there, but I need to have a way to figure out which and IF there is any activity in the foreground, so I can call it from there.
How can I possible do it?
Thanks!
Keep track of this yourself via onPause() and onResume() in each of your activities. There is nothing built in that provides this data to you.
Thinking out of the box what I did was send a notification (when the dialog was suppose to pop) that takes the user back to the activity and there it shows the dialog!
This way we don't deal with the problem to check which activity is not in front.