When ever i try to toast in service it Doesn't work But When I use LOg it Work Fine How Can I Fix this?
This is My Code Check it please:
Main Activity
public class MainActivity extends AppCompatActivity {
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn =(Button) findViewById(R.id.btnDownload);
Intent in= new Intent(this,MyService.class);
startService(in);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i=new Intent(getApplicationContext(),Main2Activity.class);
startActivity(i);
}
});
}
My Service Class: If I use Log Instead Of Toast it Works But When I Use Toast It Doesn't Show Anything...
public class MyService extends Service {
public MyService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Runnable r=new Runnable() {
#Override
public void run() {
for (int i=0 ; i<5 ; i++){
long futureTime = System.currentTimeMillis()+5000;
while (System.currentTimeMillis() < futureTime){
synchronized (this){
try {
wait(futureTime-System.currentTimeMillis());
Toast.makeText(getApplicationContext(),"Image Downloading",Toast.LENGTH_SHORT);
}catch (Exception e){}
}
}
}
}
};
Thread razasThread = new Thread(r);
razasThread.start();
return Service.START_STICKY;
}
#Override
public void onDestroy() {
Toast.makeText(getApplicationContext(),"OnDestroy method Called",Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Try doing it using Handler. It might be throwing an exception since you are trying to show the Toast on a different thread:
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
for (int i=0 ; i<5 ; i++){
long futureTime = System.currentTimeMillis()+5000;
while (System.currentTimeMillis() < futureTime){
synchronized (this){
try {
wait(futureTime-System.currentTimeMillis());
Toast.makeText(getApplicationContext(),"Image Downloading",Toast.LENGTH_SHORT).show();
}catch (Exception e){}
}
}
}
}
});
Related
I have implemented one counter and onFinish() of first counter,I started second counter but the first counter not able to finish.Text "Bye Guyz" remain for some time so how to finish the text.
Please help me.
Thanks in advance.!!!
Code :-
counter= new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
if (count == 0) {
tv.setText("First counter");
tv2.setVisibility(View.VISIBLE);
tv2.setText("Hello Guyz");
}
}
public void onFinish() {
if(!flag) {
tv2.setText("Bye Guyz");
count = 0;
try {
counter.cancel();
}catch (Exception e){}
}
else if(flag) {
counter1 = new CountDownTimer(9000, 1000) {
public void onTick(long millisUntilFinished) {
flag = false;
tv.setText("Second counter");
tv2.setVisibility(View.VISIBLE);
tv2.setText("Hello Girls");
count = 0;
}
public void onFinish() {
tv2.setVisibility(View.VISIBLE);
tv2.setText("Bye Girls");
count = 0;
}
}.start();
Did you "debug" the code to be sure the code is arriving to counter1 = new CountDownTimer(9000, 1000)?
Are you sure when the first counter arrives to onFinish() the flag variable is true?
Why do you call counter.cancel() in onFinish() when obviously the counter is already over?
public void onFinish() {
if(!flag) {
tv2.setText("Bye Guyz");
count = 0;
try {
counter.cancel();
}catch (Exception e){}
}
If you say your tv2 displays "Bye Guyz" it means that your flag is set to false, so the "else if" part is not being executed. onFinish() is only executed once, so you need to make sure the flag is set for true to start the second counter.
Also you shouldn't cancel your counter in onFinish() because it's already finished.
Here is my alternative is as follows
Create the custom Counterextending Thread
class Counter extends Thread {
private long timeOne, timeTwo;
private OnCounterFinishedListener mCounterFinishedListener;
private Thread t;
Activity activity = null;
Counter(Context context){
t = new Thread(this);
activity = (Activity)context;
}
#Override
public void run() {
try {
sleep(timeOne);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mCounterFinishedListener.firstCounterFinished();
}
});
sleep(timeTwo);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mCounterFinishedListener.secondCounterFinished();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void setTimes(long timeOne, long timeTwo){
this.timeOne = timeOne;
this.timeTwo = timeTwo;
}
public void start(OnCounterFinishedListener listener){
mCounterFinishedListener = listener;
t.start();
}
interface OnCounterFinishedListener{
void firstCounterFinished();
void secondCounterFinished();
}
}
Then inside your main thread you can start this counter as
final Counter counter = new Counter(this);
counter.setTimes(5000, 5000);
counter.start(new Counter.OnCounterFinishedListener() {
#Override
public void firstCounterFinished() {
// Update your first TextView
}
#Override
public void secondCounterFinished() {
// Update your second TextView
}
});
I run the code and get the following result, but I hope that the App can run at the order "A" -> "Service OnDestroy" -> "B" -> "C", how can I do ?
In My Way 2 section, I try to place the code into the function new Handler().postDelayed(new Runnable() {}, it's OK , it ran at the order "A" -> "Service OnDestroy" ->"B" ->"C",
I don't konw why the way can success, I don't know if the way is good way!
Result
11-13 10:04:32.137 27947-27947/info.dodata.screenrecorder E/My﹕ A
11-13 10:04:32.147 27947-27947/info.dodata.screenrecorder E/My﹕ B
11-13 10:04:32.157 27947-27947/info.dodata.screenrecorder E/My﹕ C
11-13 10:04:32.157 27947-27947/info.dodata.screenrecorder E/My﹕ Service OnDestroy
UIAbou.cs
public class UIAbout extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
stopService(intent1);
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
});
}
}
RecordService.cs
public class RecordService extends Service {
private Context mContext;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
}
#Override
public void onDestroy(){
Log.e("My","Service OnDestroy");
super.onDestroy(); //It seems that the APP is OK if I remove this.
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent,flags,startId);
}
}
=======================My Way 1 ======================================
I set a mark isServiceStoped to monitor if Stop Service is finished, but my app is hang up after disply the result "11-13 11:31:23.107 7599-7599/info.dodata.screenrecorder E/My﹕ A"
New UIAbout.cs
public class UIAbout extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this, bll.RecordService.class);
stopService(intent1);
while (RecordService.isServiceStoped==false){
//It block
}
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
});
}
}
New RecordService.cs
public class RecordService extends Service {
public static boolean isServiceStoped=true;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
}
#Override
public void onDestroy(){
Log.e("My", "Service OnDestroy");
isServiceStoped=true;
super.onDestroy(); //It seems that the APP is OK if I remove this.
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
isServiceStoped=false;
return super.onStartCommand(intent,flags,startId);
}
}
=====================My Way 2==========================================
I try to place the code into the function new Handler().postDelayed(new Runnable() {}, it's OK , it ran at the order "A" -> "Service OnDestroy" ->"B" ->"C",
I don't konw why the way can success, I don't know if the way is good way
The last UIAbout.cs
public class UIAbout extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this, bll.RecordService.class);
stopService(intent1);
new Handler().postDelayed(new Runnable() {
public void run() {
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
}, 1);
}
});
}
}
The last RecordService.cs
public class RecordService extends Service {
private Context mContext;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
}
#Override
public void onDestroy(){
Log.e("My", "Service OnDestroy");
super.onDestroy(); //It seems that the APP is OK if I remove this.
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent,flags,startId);
}
}
No, you can't stop a service synchronously. stopService() is request to stop the service. It will stop sometime later, as soon as it can.
No, you can't remove super.onDestroy() from your onDestroy() method and still have it work properly.
You can not control the timing to completely stop the running service. Use stopService() and the rest is out of your hands. You can use an handler to monitor is the service has stopped before moving to B although I am not sure why would you do it. Not a good practice.
Yeah you can remove super.onDestroy() in onDestroy but I would not advise you to do so. Your app may run but it will be leaving unwanted resources around.
Here how onDestroy() looks like in the android SDK:
#CallSuper
protected void onDestroy() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
mCalled = true;
// dismiss any dialogs we are managing.
if (mManagedDialogs != null) {
final int numDialogs = mManagedDialogs.size();
for (int i = 0; i < numDialogs; i++) {
final ManagedDialog md = mManagedDialogs.valueAt(i);
if (md.mDialog.isShowing()) {
md.mDialog.dismiss();
}
}
mManagedDialogs = null;
}
// close any cursors we are managing.
synchronized (mManagedCursors) {
int numCursors = mManagedCursors.size();
for (int i = 0; i < numCursors; i++) {
ManagedCursor c = mManagedCursors.get(i);
if (c != null) {
c.mCursor.close();
}
}
mManagedCursors.clear();
}
// Close any open search dialog
if (mSearchManager != null) {
mSearchManager.stopSearch();
}
getApplication().dispatchActivityDestroyed(this);
}
* Sample *
There could be some compile errors, but you will get the idea.
public class UIAbout extends Activity {
private Handler mHandler = new Handler();
private Runnable checkServiceHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this, bll.RecordService.class);
stopService(intent1);
checkServiceHandler = new Runnable() {
public void run() {
if(RecordService.isServiceStoped){
mHandler.removeCallbacks(checkServiceHandler );
somemethod();
} else{
mHandler.postDelayed(checkServiceHandler, 500);
}
}
};
mHandler.postDelayed(checkServiceHandler, 500); }
});
}
private void somemethod(){
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
}
You should implement your code in a way that you don't care when exactly your service is destroyed.
Anyway. If you really need the exact moment, you can fire an intent from your service using Android's broadcast system.
In your service:
#Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(CONST_SERVICE_DESTROYED));
}
In your activity:
private BroadcastReceiver receiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
// your B here
// your C here
}
};
And you need to register and unregister your receiver like this:
#Override
protected void onResume()
{
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, new IntentFilter(CONST_SERVICE_DESTROYED));
}
#Override
protected void onPause()
{
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
A good explanation and examples of Android's broadcast system can be found here
I have a simple Service
public class UpdateService extends Service {
private int seconds;
final static String MY_ACTION = "MY_ACTION";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
timer.start();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
final CountDownTimer timer = new CountDownTimer(86400000, 1000) {
public void onTick(long millisUntilFinished) {
Util.saveInfo(getApplicationContext(), Util.SECONDS, seconds++);
Intent intent = new Intent();
intent.setAction(MY_ACTION);
sendBroadcast(intent);
}
public void onFinish() { }
};
}
When I close an application service stops working. But showing that the service is running.
What am I doing wrong?
Update
I changed CountDownTimer to Thread, but the problem remained
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
Util.saveInfo(getApplicationContext(), Util.SECONDS, seconds++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
OnStart()
if(!t1.isAlive())
t1.start();
Because CountDown Timer is working only foreground means app is running and not minimized or closed. You have to place a Thread in Service that executing at particular time of you want.
try this :
public class LocalService extends Service
{
private static Timer timer = new Timer();
private Context ctx;
public IBinder onBind(Intent arg0)
{
return null;
}
public void onCreate()
{
super.onCreate();
ctx = this;
startService();
}
private void startService()
{
timer.scheduleAtFixedRate(new mainTask(), 0, 5000);
}
private class mainTask extends TimerTask
{
public void run()
{
toastHandler.sendEmptyMessage(0);
}
}
public void onDestroy()
{
super.onDestroy();
Toast.makeText(this, "Service Stopped ...", Toast.LENGTH_SHORT).show();
}
private final Handler toastHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
System.out.println("test");
}
};
}
I have a checked button in my MainActivity. If that button is checked it should start the service but if a user unchecked the button I want to stop the service.
So in uncheck condition I have written this stopService(intentname); but the problem is the service is not stopping. Here is my code snippet:
Service Class
public class SimpleService extends Service
{
String selectedAudioPath = "";
private MyThread myythread;
public Intent intent;
public boolean isRunning = false;
long interval=30000;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
myythread = new MyThread(interval);
}
#Override
public synchronized void onDestroy()
{
super.onDestroy();
if(!isRunning)
{
myythread.interrupt();
myythread.stop();
isRunning = false;
}
}
#Override
public synchronized void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
if(!isRunning)
{
//this.intent = intent;
//System.out.println("the intent is" + intent);
myythread.start();
isRunning = true;
}
}
class MyThread extends Thread
{
long interval;
public MyThread(long interval)
{
this.interval=interval;
}
#Override
public void run()
{
while(isRunning)
{
System.out.println("Service running");
try
{
String myString = intent.getStringExtra("name");
if(myString == null)
Log.d("Service","null");
else
{
Log.d("Service","not null");
if(myString.equalsIgnoreCase("image"))
{
uploadImages();
Thread.sleep(interval);
}
else if(myString.equalsIgnoreCase("audio"))
{
uploadAudio();
Thread.sleep(interval);
}
}
}
catch (InterruptedException e)
{
isRunning = false;
e.printStackTrace();
}
}
}
You can't stop a thread that has a running unstoppable loop like this
while(true)
{
}
To stop that thread, declare a boolean variable and use it in while-loop condition.
public class MyService extends Service {
...
private Thread mythread;
private boolean running;
#Override
public void onDestroy()
{
running = false;
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startid) {
running = true;
mythread = new Thread() {
#Override
public void run() {
while(running) {
MY CODE TO RUN;
}
}
};
};
mythread.start();
}
Source: Stopping a thread inside a service
Don't use Threads. Use AsyncTask instead.
public class MyService extends Service {
private AsyncTask<Void,Void,Void> myTask;
#Override
public void onDestroy(){
super.onDestroy();
myTask.cancel(true);
}
#Override
public void onStart(Intent intent, int startid) {
myTask = new AsyncTask<Void,Void,Void>(){
#Override
public void doInBackground(Void aVoid[]){
doYourWorkHere();
}
}
myTask.execute();
}
}
I write a Splash Screeen to run at the boot time of application
public class SplashScreen extends Activity {
ImageView imgView;
int[] imgID = new int[]{R.drawable.frame0, R.drawable.frame1, R.drawable.frame2, R.drawable.frame3,
R.drawable.frame4, R.drawable.frame5, R.drawable.frame6};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
imgView = (ImageView) findViewById(R.id.imgSplash);
new Thread(new WelcomeScreen()).start();
}
private class WelcomeScreen implements Runnable {
#Override
public void run() {
try {
for (int i = 0; i < imgID.length; i++)
{
imgView.setImageResource(imgID[i]);
sleep(500);
}
} catch (InterruptedException e) {
}finally {
Intent intent = new Intent(SplashScreen.this,LoginActivity.class);
startActivity(intent);
finish();
}
}
}
}
It getting error "Sorry the application has stopped unexpectedly" . I don't know why . Somebody can help me ????
you can not set the resource for yuor ImageView inside a thread different from the UI Thread.
you can use runOnUiThread. It takes as paramter a runnable, and post it in the UI Thread queue. There, the UI thead takes it and update your ImageView. All in all your runnable will become:
private class WelcomeScreen implements Runnable {
#Override
public void run() {
try {
for (int i = 0; i < imgID.length; i++)
{
final int resuorceId = imgID[i];
runOnUiThread(new Runnable() {
#Override
public void run() {
imgView.setImageResource(resuorceId);
}
});
sleep(500);
}
} catch (InterruptedException e) {
}finally {
Intent intent = new Intent(SplashScreen.this,LoginActivity.class);
startActivity(intent);
finish();
}
}
You can not access your views from Thread.
You will need to put your code imgView.setImageResource(imgID[i]); in runOnUiThread
use like:
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
imgView.setImageResource(imgID[i]);
}
});
Thanks
You can not change something in UI from non-UI thread so replace this you code:
imgView.setImageResource(imgID[i]);
to:
runOnUiThread(new Runnable() {
#Override
public void run() {
imgView.setImageResource(imgID[i]);
}
});
//try code this way...
public class SplashScreen extends Activity {
private Intent launchIntent;
private Thread splashThread; //used for perform splash screen operation
private int splashTime = 10000, sleepTime = 50; //used for threading operation
private boolean active = true; //used for touch event
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splashscreen); //Set splashscreen.xml here
try {
splashThread = new Thread() { // Creating Thread for splash the screen
#Override
public void run() { // run method implemented to perform threading operation
try {
int waitTime = 0; //counter for threading
do {
sleep(sleepTime); //delay for specific time
if (active)
waitTime += 100;
//write your image code here that display your no. of images
} while (active && (waitTime < splashTime)); //Check touch condition and counter
} catch (Exception e) {
// to handle runtime error of run method
Validation.displayToastMessage(SplashScreen.this, e.toString()); //Call static method of class ToastMessage
}
finish(); //finish current activity
startJustCoupleActivityScreen(); //Call below defined function
}
};
splashThread.start(); //start thread here
} catch (Exception e) {
message("SplashScreen : "+ e.toString()); //Call static method of class ToastMessage
}
}
public void startJustCoupleActivityScreen() {
launchIntent=new Intent(SplashScreen.this,JustCoupleActivity.class); //call Next Screen
startActivity(launchIntent); //start new activity
}
#Override
public boolean onTouchEvent(MotionEvent event) { //onTouch Event
//on touch it immediate skip splash screen
if(event.getAction()==MotionEvent.ACTION_DOWN) active=false; //Check Touch happened or not
return true;
}
public void message(String msg)
{
Validation.displayToastMessage(SplashScreen.this, msg); //display Error Message
}
}