0

I am trying to Run this Code Example and I have replaced readWebPage() method with my own codes.

I am trying to implement CHAT HEADS inside a service.

Log Cat

03-10 00:22:00.309: E/AndroidRuntime(9302): FATAL EXCEPTION: Thread-596
03-10 00:22:00.309: E/AndroidRuntime(9302): Process: com.example.soc, PID: 9302
03-10 00:22:00.309: E/AndroidRuntime(9302): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
03-10 00:22:00.309: E/AndroidRuntime(9302):     at android.os.Handler.<init>(Handler.java:200)
03-10 00:22:00.309: E/AndroidRuntime(9302):     at android.os.Handler.<init>(Handler.java:114)
03-10 00:22:00.309: E/AndroidRuntime(9302):     at android.view.ViewRootImpl$ViewRootHandler.<init>(ViewRootImpl.java:2968)
03-10 00:22:00.309: E/AndroidRuntime(9302):     at android.view.ViewRootImpl.<init>(ViewRootImpl.java:3248)
03-10 00:22:00.309: E/AndroidRuntime(9302):     at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:248)
03-10 00:22:00.309: E/AndroidRuntime(9302):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
03-10 00:22:00.309: E/AndroidRuntime(9302):     at com.example.soc.msgService.readWebPage(msgService.java:98)
03-10 00:22:00.309: E/AndroidRuntime(9302):     at com.example.soc.msgService$MyThread.run(msgService.java:108)

MainActivity.java

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    startService(new Intent(MainActivity.this, msgService.class));
}

msgService.java

package com.example.soc;

import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;

import com.example.soc.util.ImageLoadTask;
import com.squareup.picasso.Picasso;

import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.WindowManager;
import android.widget.ImageView;

public class msgService extends Service{

    private static String TAG = msgService.class.getSimpleName();
    private MyThread mythread;
    public boolean isRunning = false;
    private WindowManager windowManager;
    private ImageView chatHead;    
    String url = "someimageurl.jpg"; 

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");     
        mythread  = new MyThread();
    }

    @Override
    public synchronized void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
        if(!isRunning){
            mythread.interrupt();
            mythread.stop();
        }       
    }

    @Override
    public synchronized void onStart(Intent intent, int startId) {
        super.onStart(intent, startId); 
        Log.d(TAG, "onStart");
        if(!isRunning){
            mythread.start();
            isRunning = true;
        }
    }

    public void readWebPage(){

          windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

          chatHead = new ImageView(this);
          Picasso.with(this).load(url).into(chatHead);



          WindowManager.LayoutParams params = new WindowManager.LayoutParams(
              WindowManager.LayoutParams.WRAP_CONTENT,
              WindowManager.LayoutParams.WRAP_CONTENT,
              WindowManager.LayoutParams.TYPE_PHONE,
              WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
              PixelFormat.TRANSLUCENT);

          params.gravity = Gravity.TOP | Gravity.LEFT;
          params.x = 0;
          params.y = 100;

          windowManager.addView(chatHead, params);          
    }

    class MyThread extends Thread{
        static final long DELAY = 3000;
        @Override
        public void run(){          
            while(isRunning){
                Log.d(TAG,"Running");
                try {                   
                    readWebPage();

                    Thread.sleep(DELAY);
                } catch (InterruptedException e) {
                    isRunning = false;
                    e.printStackTrace();
                }
            }
        }

    }

}
Slim Shady
  • 1,045
  • 2
  • 12
  • 38
  • You could call `Looper.prepare()` – Jay Snayder Mar 09 '15 at 19:04
  • But where @JaySnayder will i call `Looper.prepare()` – Slim Shady Mar 09 '15 at 19:05
  • Within `readWebPage()` – Jay Snayder Mar 09 '15 at 19:06
  • @JaySnayder. No. That is not the answer. This is a basic, well known Android design concept, and you are only misdirecting the poster from solving it. – Chris Stratton Mar 09 '15 at 19:12
  • `E/AndroidRuntime(11424): java.lang.IllegalStateException: Method call should happen from the main thread.` @JaySnayder – Slim Shady Mar 09 '15 at 19:13
  • Then you did not take time to read and apply the solution presented there. Your problem is exactly the same - only the operations you are illegally trying to do from the background differ, but they fail for the same reason that touching the UI from the background is prohibited, and are solved by applying the same methods suggested there. – Chris Stratton Mar 09 '15 at 19:16
  • See [STEP 2: Call the Looper methods on this page](http://techtej.blogspot.com.br/2011/02/android-passing-data-between-main.html) and try calling Looper.prepare() and Looper.loop() after run() – walljam7 Mar 09 '15 at 19:17
  • Again, no. Messing with loopers will not solve the fundamental problem that you are not allowed to touch the UI from any thread other than the UI thread. It is not a multithreaded UI paradigm. – Chris Stratton Mar 09 '15 at 19:17
  • Can you give an example based on my codes @ChrisStratton – Slim Shady Mar 09 '15 at 19:25
  • use runOnUiThread() to put your ui operations back on the main thread just as suggested there. – Chris Stratton Mar 09 '15 at 19:33
  • `runOnUiThread()` needs activity context to run i.e`activity.runOnUiThread(new Runnable() {//run method});` but here `activity` is undefined in my above code @ChrisStratton – Slim Shady Mar 09 '15 at 19:36
  • Of course; you shouldn't be touching the UI from a service either, since there won't necessarily *be* a ui to touch, but apart from needing the Context to which the UI belongs, there aren't safety checks enforced on it, just potential pitfalls. You really should use an Intent to send results back to your Activity, bringing it up if necessary. Otherwise you can define a callback method in your Activity, but be careful to check that things are still valid! – Chris Stratton Mar 09 '15 at 19:58

0 Answers0