2

When I was working with an application, I came to know that inside AsycTask I can't use Toast directly unless it's a handler. So With handlers it's working fine so far. The Toast as a handler as follows

private void threadMsg(String msg) {

        if (!msg.equals(null) && !msg.equals("")) {
            Message msgObj = handler.obtainMessage();
            Bundle b = new Bundle();
            b.putString("message", msg);
            msgObj.setData(b);
            handler.sendMessage(msgObj);
        }
}

private final Handler handler = new Handler() {

        public void handleMessage(Message msg) {

            String aResponse = msg.getData().getString("message");

            if ((null != aResponse)) {
                // ALERT MESSAGE
                Toast.makeText(
                        getBaseContext(),
                        "Server Response: " + aResponse,
                        Toast.LENGTH_SHORT).show();
                progressBarHolder.setVisibility(View.INVISIBLE);
            }
            else
            {

                // ALERT MESSAGE
                Toast.makeText(
                        getBaseContext(),
                        "Not Got Response From Server.",
                        Toast.LENGTH_SHORT).show();
            }
        }
};

I'm just calling threadMsg("Message"); in my AsycTask and it's working fine. But In my new Requirement, I happens to call AsycTask from a Service. And When I execute it, I'm getting a Null pointer exception on Toast.
I'm not understanding what's happening in this scenario. Please help me in solving this.

Edit: Service Code Where I'm executing AsycTask

public class FirstService extends Service {

   TayKitDatabaseOpenHelper db = new TayKitDatabaseOpenHelper(this);
   private MyApplication app;
   /** indicates how to behave if the service is killed */
   int mStartMode;

   /** interface for clients that bind */
   IBinder mBinder;

   /** indicates whether onRebind should be used */
   boolean mAllowRebind;

   /** Called when the service is being created. */
   @Override
   public void onCreate() {
     app = (MyApplication) getApplication();
     AsycInvokerActivity.OrderDeliveryAsyTask sm=new  
     AsycInvokerActivity().new OrderDeliveryAsyTask(orderDelivered);
     sm.execute();
   }
   public void onStart(Intent intent, int startId) {
      System.out.println("insuide service omstart");

   }

   /** The service is starting, due to a call to startService() */
   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
      System.out.println("inside FirstServece's onStartCommand");
      List<OrderDeliveryModel> deliveredOrders =   
      db.getAllDeliveredOrdersByUserId(app.getPudoType());
      System.err.println("Total Number or orders which has to be synced: 
      "+deliveredOrders.size());

      return mStartMode;
   }

   /** A client is binding to the service with bindService() */
   @Override
   public IBinder onBind(Intent intent) {
     return mBinder;
   }

   /** Called when all clients have unbound with unbindService() */
   @Override
   public boolean onUnbind(Intent intent) {
     return mAllowRebind;
   }

   /** Called when a client is binding to the service with bindService()*/
   @Override
   public void onRebind(Intent intent) {

   }

   /** Called when The service is no longer used and is being destroyed */
   @Override
   public void onDestroy() {

   }
 }

Edit: Stack Trace

java.lang.NullPointerException
        at android.widget.Toast.<init>(Toast.java:92)
        at android.widget.Toast.makeText(Toast.java:233)
        at com.example.databaseUtils.offlineDataUtils.AsycInvokerActivity$OrderDeliveryAsyTask$1.run(AsycInvokerActivity.java:174)
        at android.os.Handler.handleCallback(Handler.java:605)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4441)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:823)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:590)
        at dalvik.system.NativeStart.main(Native Method)
Kishore Kumar Korada
  • 1,204
  • 6
  • 22
  • 47

5 Answers5

1

The problem is that Service is not running n UI Thread. You can show Toast via an Activity:

@Override
public void onCreate() {
    super.onCreate();
    mHandler = new Handler();
}
@Override
protected void onHandleIntent(Intent intent) {
    mHandler.post(new Runnable() {            
        @Override
        public void run() {
            Toast.makeText(MyIntentService.this, 
                "Hello Toast!", Toast.LENGTH_LONG).show();                
        }
    });
}
JavaGhost
  • 406
  • 4
  • 8
1

To display Toast anywhere in android, we need a UI Thread.Only UI thread can interact with UI stuffs and render it for example Toast,Dialog,Progressbar etc.

Hence Create a UI(Runnable) thread as mentioned below inside the IntentService :-

private Handler handler;
handler = new Handler();  
handler.post(new Runnable() {
        public void run() {


            try {

                System.out.println("inside FirstService's onStartCommand");
                List<OrderDeliveryModel> deliveredOrders = db.getAllDeliveredOrdersByUserId(app.getPudoType());
                System.err.println("Total Number or orders which has to be synced: "+deliveredOrders.size());

                for(OrderDeliveryModel orderDelivered : deliveredOrders) {
                    AsycInvokerActivity.OrderDeliveryAsyTask sm=new AsycInvokerActivity().new OrderDeliveryAsyTask(orderDelivered,context);
                    sm.execute();
                }
            } catch (Exception e) {
                System.err.println("Error in catch is "+e);
                //Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
            }
        }
    });

And pass the context

Context context;
context = getApplicationContext();

of IntentService to The Constructor of AsyncTask and use the passed context inside the toast of handler to display Toast Successfully.

suri
  • 183
  • 2
  • 13
0

You Need use UI Thread to display Toast in AsyncTask

runOnUiThread(new Runnable(){

          @Override
          public void run(){
            //update ui here
            // display toast here 
          }
       });

When you call your threadMsg Method from a service ,you cant use its context,because Activty and Service both have Different Life Cycles

Try using IntentService

http://developer.android.com/reference/android/app/IntentService.html

Rajan Kali
  • 12,627
  • 3
  • 25
  • 37
0

Pass context from your activity where the service is called and this context is write in your toast message and it solve your error.

Ganpat Kaliya
  • 888
  • 2
  • 9
  • 16
0

Finally Found the solution for the question. The Problem was...

The AsyncTask was in some Activity, and I'm passing it's(Activity's) context to the Toast. It worked for me whenever I invoked the AsyncTask from the same Activity. But, When ever I tried to invoke that AsyncTask from a Service, I was getting NullPointerException since that Toast is using same Activity's context.
So I had to pass Service's context to the AsyncTask. And It Worked !!!

Kishore Kumar Korada
  • 1,204
  • 6
  • 22
  • 47