I've a boot screen structured in this way:
public class BootActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_boot);
Thread welcomeThread = new Thread() {
#Override
public void run() {
try {
super.run();
sleep(2000);
} catch (Exception e) {
} finally {
Intent i = new Intent(BootActivity.this,
Main_activity.class);
startActivity(i);
finish();
}
}
};
welcomeThread.start();
}
}
I've added into layout R.layout.activity_boot an HD background image. I'll use this screen to load some things to use after in my main activity. I've read that activity goes in background and it's paused when another activity is opened and continue to occupy memory space. I've performed App memory monitoring and found that I've about 50Mb of memory used when BootActivity is opened. Since this activity will never be opened again, how should I clear memory to have more memory space for next Activity?
Add System.exit(0); after finish();
#Override
public void run() {
try {
super.run();
sleep(2000);
} catch (Exception e) {
} finally {
Intent i = new Intent(BootActivity.this,
Main_activity.class);
startActivity(i);
finish();
System.exit(0);
}
it may clear some memory
Also you can use intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK) with intent it will remove activity from back stack
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Related
I'm using a thread to set an image as background and in this thread i have a dialog. The dialog starts and should be close when the wallpaper will be set. This is the code so far
setWallbtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
final ProgressDialog myPd_ring=ProgressDialog.show(SingleWall.this, "Setting wallpaper", "", true);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
WallpaperManager wallManager = WallpaperManager.getInstance(getApplicationContext());
try {
image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
wallManager.setBitmap(image);
Toast.makeText(SingleWall.this, "Wallpaper Set Successfully!!", Toast.LENGTH_SHORT).show();
myPd_ring.dismiss();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(SingleWall.this, "Setting WallPaper Failed!!", Toast.LENGTH_SHORT).show();
myPd_ring.dismiss();
}
}
}, 4000);
}
});
So, on click in a button starts the thread and for 4 seconds the dialog should be visible with the progress icon. But it is not correct! the time to set the background could be more or less than 4 seconds! So the 4000 should be calculates in base of the time to set the image as wallpaper. Is it possible?
ps. I can't use a AsyncTask because i get many NullPointerExceptions
Note that you are not using a separate Thread with the code in your question, you are running a Runnable on the main UI thread.
If you look at the documentation, it's recommended to use an AsyncTask for decoding Bitmaps, and it's also the best way to achieve your desired result, where the ProgressDialog is dismissed only after the process is complete, which can take an unpredictable amount of time.
You just need to put the code in it's correct place, and give it what it needs through the varargs passed in.
Here is how you should start the AsyncTask:
setWallbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new LoadImage().execute(url);
}
});
Then, create the AsyncTask as a sub-class of the SingleWall Activity.
Put the network code in doInBackground() which will download and decode the Bitmap, and then put the UI related code in onPostExecute(), which runs on the UI thread.
Note that you can also use a WeakReference to the WallpaperManager instance, as outlined in the link above, but I'll keep it simple here and just access wallManager directly, which you can do if the AsyncTask is a sub-class of your Activity.
class LoadImage extends AsyncTask<URL, Void, Bitmap> {
ProgressDialog myPd_ring;
#Override
protected void onPreExecute() {
//Start Progress Dialog here
myPd_ring = ProgressDialog.show(SingleWall.this, "Setting wallpaper", "", true);
}
//Runs in a background Thread
#Override
protected Bitmap doInBackground(URL... params) {
URL url = params[0];
Bitmap image = null;
try {
image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
//Runs on the UI Thread
#Override
protected void onPostExecute(Bitmap image) {
myPd_ring.dismiss();
if (image == null){
Toast.makeText(SingleWall.this, "Setting WallPaper Failed!!", Toast.LENGTH_LONG).show();
}
else{
//set image here
try {
SingleWall.this.wallManager.setBitmap(image);
Toast.makeText(SingleWall.this, "Wallpaper Set Successfully!!", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(SingleWall.this, "Setting WallPaper Failed!!", Toast.LENGTH_LONG).show();
}
}
}
}
Use the AsyncTask, the null pointers are probably coming because you are trying to update the UI during the task's processing. You might need to use something like this from inside the AsyncTask:
activity.runOnUiThread(new Runnable() {
public void run() {
activity.doSomeSpecialUIWork();
}
});
}
Hope that works - that's what solved it for me when I was getting strange null pointers during an AsyncTask.
Here's an example from another post: how to use runOnUiThread
For your specific code, maybe this:
setWallbtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
activity.runOnUiThread(new Runnable() {
public void run() {
final ProgressDialog myPd_ring=ProgressDialog.show(SingleWall.this, "Setting wallpaper", "", true);
// TODO Auto-generated method stub
WallpaperManager wallManager = WallpaperManager.getInstance(getApplicationContext());
try {
image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
wallManager.setBitmap(image);
Toast.makeText(SingleWall.this, "Wallpaper Set Successfully!!", Toast.LENGTH_SHORT).show();
myPd_ring.dismiss();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(SingleWall.this, "Setting WallPaper Failed!!", Toast.LENGTH_SHORT).show();
myPd_ring.dismiss();
}
}
});
}
}
});
I have 2 layouts, and 2 activities, each one corresponding to a layout, one of them is SplashActivity, and the other is MainActivity. I want the application to open the splashActivity(splash XML shows the logo), wait for 5 seconds and open the main activity, but because of the thread, the setContentView doesn't work properly.
P.S. Also any relative documentation links would be very useful, thanks in advance
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
Thread timer = new Thread() {
public void run() {
try {
sleep(5000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
try {
Class mainMenu = Class.forName("com.carmine.project.MenuActivity");
Intent openMainMenu = new Intent(SplashActivity.this, mainMenu);
startActivity(openMainMenu);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
};
timer.run();
}
your problem is that you are calling timer.run(); instead of timer.start();
timer.run(); calls the run method on the same context of the thread that executed that line (making the UI Thread, in your case, wait for 5s, and blocking every other operation). timer.start() spawns a new thread
I am trying to build an app that works as an alarm clock. I implemented everything with help of the AlarmManager and it works fine. But I have one problem, when the alarm rings it starts an Activity which shows a screen with a button and plays a sound. But it shows only a black screen and vibrates + plays the sound and then after that it shows the alarm screen.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.wecker);
laufen = true;
mp = MediaPlayer.create(getApplicationContext(), R.raw.ton);
verstanden =(Button)findViewById(R.id.button1);
verstanden.setOnClickListener(new View.OnClickListener() {public void onClick(View view)
{
finish();
}
});
for (int i=0; i<10;i++)
{
mp.start();
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(1000);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
What can I do to show the activity and play the sound simultaneously?
Thread.sleep(1000); Blocks your UI Thread hence, the black screen shows up.
Use this :
new Thread( new Runnable() {
public void run() {
try {
// Add loop to play music and vibrate here
} catch (InterruptedException ie) {}
}
) }.start();
You have put Thread.sleep(1000); in your onCreate() method which is on your UI Thread. Your activity's UI only shows up at onResume() which is after onCreate() so it doesn't get there until your sleep commands are finished. You need to create a new Thread and run the vibrator/sleep cycle on that Thread. Usage is shown in Shivam Verma's answer.
I have three images with me and i want them to appear on first layout xml like a splash view so that they can be viewed only once i.e that activity will be called only once when app get's installed or if app get's a new update otherwise app should always start from the Second activity, i don't know how should i begin with this :
Can any one tell me any idea how this can be done.
To show splash for only once.
Next part of this question is here
Coding will be much appreciated.
Save a flag in the Preferences when you start up the application, after you've done the welcome screen stuff. Check for this flag before you show the welcome screen. If the flag is present (in other words, if it's not the first time), don't show it.
In your activity:
SharedPreferences mPrefs;
final String welcomeScreenShownPref = "welcomeScreenShown";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
// second argument is the default to use if the preference can't be found
Boolean welcomeScreenShown = mPrefs.getBoolean(welcomeScreenShownPref, false);
if (!welcomeScreenShown) {
// here you can launch another activity if you like
// the code below will display a popup
String whatsNewTitle = getResources().getString(R.string.whatsNewTitle);
String whatsNewText = getResources().getString(R.string.whatsNewText);
new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(whatsNewTitle).setMessage(whatsNewText).setPositiveButton(
R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(welcomeScreenShownPref, true);
editor.commit(); // Very important to save the preference
}
}
Try this :
public class MainActivity extends Activity {
private Thread mSplashThread;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.splash);
final MainActivity sPlashScreen = this;
mSplashThread = new Thread() {
#Override
public void run() {
try {
synchronized (this) {
wait(4000);
}
} catch (InterruptedException ex) {
}
finish();
Intent intent = new Intent();
intent.setClass(sPlashScreen, StartNewActivity.class);// <-- Activity you want to start after Splash
startActivity(intent);
}
};
mSplashThread.start();
} catch (Exception e) {
}
}
#Override
public boolean onTouchEvent(MotionEvent evt) {
try {
if (evt.getAction() == MotionEvent.ACTION_DOWN) {
synchronized (mSplashThread) {
mSplashThread.notifyAll();
}
}
} catch (Exception e) {
}
return true;
}
}
you put an Image in splash.xml to show
to do this you have to detect the first launch of your application. To do so you can store a boolean value as #Nirav suggested.
And for the splash screen, You can consider using Fragments and ViewPager to create an activity which will only be shown for the first time
I have a Splash Screen (Logo Activity) to show the company name for 3 seconds before app starts. I start Main Activity from a thread, here is the code:
public class Logo extends Activity {
Thread t;
public boolean dead = false;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.logo);
t = new Thread() {
public void run() {
try {
Intent i = new Intent(Logo.this, Main.class);
Thread.sleep(3000);
if (!dead) {
startActivity(i);
}
finish();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.start();
}
The Main Activity is called from a worked thread, is this correct? What are the differents with this code (using runOnUiThread)?
...
if (!dead) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Intent i = new Intent(Logo.this, Main.class);
startActivity(i);
}
});
}
...
I see no difference with this code in debug mode (The same threads, the same operation, etc.). Which is correct?
Starting an intent I think is not an UI operation. runOnUI thread runs UI operation on UI thread. So you can use either of thread (runOnUI or normal). May be normal thread will be good in this situation. But I would like to suggest you use timer instead.
To be honest, I don't like the Thread.sleep. PLease take a look at my solution:
new Timer().schedule(new TimerTask() {
#Override
public void run() {
// Do your work here like... startActivity...
}
}, SPLASH_DURATION); // SPLASH_DURATION IS IN MILLISECONDS LIKE 3000
Also you can block the user to prevent the back key like this:
#Override
public void onBackPressed() {
// do nothing! disable user interaction!
}
You should use AsyncTask in "doInBackground" background thread and than sleep your thread(this thread not UIThread) "PostExecute" run on UI Thread than start your new activity
private class mSplashViewer extends AsyncTask<Void,Void,Void>{
protected void doInBackground(Void params){
Thread.currentThread().sleep(3000);
return null;
}
protected void onPostExecute(){
startActivity(...);
}
}