Search code examples
androidlistviewwindow-managers

Dynimically load ListView. Refresh ListView after every n sec


Below is my code that show an overlay with a list view that shows some information. I am updating the data after every 7 sec. I want to remove first list before displaying other. In may case the ListViews are overlapping.

public class OverlayShowingService extends Service implements OnTouchListener,               OnClickListener {

private View topLeftView;

private Button overlayedButton;
ArrayList<String> list = new ArrayList<String>();

/** Declaring an ArrayAdapter to set items to ListView */
ArrayAdapter<String> adapter;
private float offsetX;
private float offsetY;
private int originalXPos;
private int originalYPos;
private boolean moving;
private WindowManager wm;
DispAsync dis;
ListView listView;

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

@Override
public void onCreate() {
super.onCreate();
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // TODO Auto-generated method stub

    Toast.makeText(getApplicationContext(),"onStartCommand", Toast.LENGTH_LONG).show();

    listView = new ListView(getApplicationContext());
    listView.setAlpha(0.0f);
    listView.setBackgroundColor(0x55fe4444);



       final Handler handler = new Handler();
        Timer timer = new Timer();
        TimerTask doAsynchronousTask = new TimerTask() {       
            @Override
            public void run() {
                handler.post(new Runnable() {
                    public void run() {       
                        try {
                            dis=new DispAsync();
                            dis.execute();
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                        }
                    }
                });
            }
        };
        timer.schedule(doAsynchronousTask, 0, 7000); //execute in every 50000 ms



    return super.onStartCommand(intent, flags, startId);
}

public class DispAsync extends AsyncTask<Void, Void, String>
{
    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub

        Toast.makeText(getApplicationContext(),"onPre", Toast.LENGTH_LONG).show();
        //list.clear();
        adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, list);
        listView.setAdapter(adapter);
        super.onPreExecute();
    }

    @Override
    protected String doInBackground(Void... params) {
        // TODO Auto-generated method stub
        String line = null;
        wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);


        try
        {

            line = dynamic data;
            while (line != null) {
                if(line.contains("com"))
                {list.add(line);}
                line = reader.readLine();
                i++;
            }

            p.waitFor();
        }
        catch(Exception e){}



        return line;
    }

    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub

        Toast.makeText(getApplicationContext(),"onPost", Toast.LENGTH_LONG).show();
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.LEFT | Gravity.TOP;
        params.x = 0;
        params.y = 0;
        //adapter.notifyDataSetChanged();
        wm.addView(listView, params);

   /*   topLeftView = new View(getApplicationContext());
        WindowManager.LayoutParams topLeftParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
        topLeftParams.gravity = Gravity.LEFT | Gravity.TOP;
        topLeftParams.x = 0;
        topLeftParams.y = 0;
        topLeftParams.width = 0;
        topLeftParams.height = 0;
        wm.addView(topLeftView, topLeftParams);*/

        super.onPostExecute(result);
    }

}
@Override
public void onDestroy() {
super.onDestroy();
if (overlayedButton != null) {
    wm.removeView(overlayedButton);
    wm.removeView(topLeftView);
    overlayedButton = null;
    topLeftView = null;
}
}

@Override
public boolean onTouch(View v, MotionEvent event) {

if (event.getAction() == MotionEvent.ACTION_DOWN) {
    float x = event.getRawX();
    float y = event.getRawY();

    moving = false;

    int[] location = new int[2];
    overlayedButton.getLocationOnScreen(location);

    originalXPos = location[0];
    originalYPos = location[1];

    offsetX = originalXPos - x;
    offsetY = originalYPos - y;

} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
    int[] topLeftLocationOnScreen = new int[2];
    topLeftView.getLocationOnScreen(topLeftLocationOnScreen);

    System.out.println("topLeftY="+topLeftLocationOnScreen[1]);
    System.out.println("originalY="+originalYPos);

    float x = event.getRawX();
    float y = event.getRawY();

    WindowManager.LayoutParams params = (LayoutParams) overlayedButton.getLayoutParams();

    int newX = (int) (offsetX + x);
    int newY = (int) (offsetY + y);

    if (Math.abs(newX - originalXPos) < 1 && Math.abs(newY - originalYPos) < 1 && !moving) {
    return false;
    }

    params.x = newX - (topLeftLocationOnScreen[0]);
    params.y = newY - (topLeftLocationOnScreen[1]);

    wm.updateViewLayout(overlayedButton, params);
    moving = true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
    if (moving) {
    return true;
    }
}

return false;
}

@Override
public void onClick(View v) {
Toast.makeText(this, "Overlay button click event", Toast.LENGTH_SHORT).show();
} 
}

logcat

08-11 16:00:55.175: E/AndroidRuntime(11498): FATAL EXCEPTION: main
08-11 16:00:55.175: E/AndroidRuntime(11498): Process: de.mobilej.overlay, PID: 11498
08-11 16:00:55.175: E/AndroidRuntime(11498): java.lang.IllegalStateException: View android.widget.ListView{41db9c50 V.ED.VC. ......I. 0,0-480,422} has already been added to the window manager.
08-11 16:00:55.175: E/AndroidRuntime(11498):    at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:232)
08-11 16:00:55.175: E/AndroidRuntime(11498):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
08-11 16:00:55.175: E/AndroidRuntime(11498):    at de.mobilej.overlay.OverlayShowingService$DispAsync.onPostExecute(OverlayShowingService.java:151)
08-11 16:00:55.175: E/AndroidRuntime(11498):    at de.mobilej.overlay.OverlayShowingService$DispAsync.onPostExecute(OverlayShowingService.java:1)
08-11 16:00:55.175: E/AndroidRuntime(11498):    at android.os.AsyncTask.finish(AsyncTask.java:632)
08-11 16:00:55.175: E/AndroidRuntime(11498):    at android.os.AsyncTask.access$600(AsyncTask.java:177)
08-11 16:00:55.175: E/AndroidRuntime(11498):    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
08-11 16:00:55.175: E/AndroidRuntime(11498):    at android.os.Handler.dispatchMessage(Handler.java:110)
08-11 16:00:55.175: E/AndroidRuntime(11498):    at android.os.Looper.loop(Looper.java:193)
08-11 16:00:55.175: E/AndroidRuntime(11498):    at android.app.ActivityThread.main(ActivityThread.java:5388)
08-11 16:00:55.175: E/AndroidRuntime(11498):    at java.lang.reflect.Method.invokeNative(Native Method)
08-11 16:00:55.175: E/AndroidRuntime(11498):    at java.lang.reflect.Method.invoke(Method.java:515)

Solution

  • Issue is with Listview creation. Currnetly everytime AsynTask is created it is creating the new list view. just create your list view outside of asynctask and global to class so that you can access this listview object within asyncTask like below

    private ListView listView;
    

    initialige this listView in your relevant location like below.

        listView = new ListView(getApplicationContext());
        listView.setAlpha(0.0f);
        listView.setBackgroundColor(0x55fe4444);
        adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, list);
        listView.setAdapter(adapter);
                WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.LEFT | Gravity.TOP;
        params.x = 0;
        params.y = 0;
        wm.addView(listView, params);
    

    In your onPostExcute of your asyncTask update your adaper for any list data change like below

    adapter.notifyDataSetChanged(); 
    

    Edit

    Complete fix for the reference

     public class OverlayShowingService extends Service implements OnTouchListener, OnClickListener { 
    
    private View topLeftView; 
    
    private Button overlayedButton; 
    ArrayList<String> list = new ArrayList<String>(); 
    
    /** Declaring an ArrayAdapter to set items to ListView */ 
    ArrayAdapter<String> adapter; 
    private float offsetX; 
    private float offsetY; 
    private int originalXPos; 
    private int originalYPos; 
    private boolean moving; 
    private WindowManager wm; 
    DispAsync dis; 
    ListView listView; 
    
    @Override 
    public IBinder onBind(Intent intent) { 
    return null; 
    } 
    
    @Override 
    public void onCreate() { 
    super.onCreate(); 
    } 
    
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
    
    listView = new ListView(getApplicationContext()); 
    listView.setAlpha(0.0f); 
    listView.setBackgroundColor(0x55fe4444); 
    
    wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); 
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT); 
    params.gravity = Gravity.LEFT | Gravity.TOP; 
    params.x = 0; 
    params.y = 0; 
    wm.addView(listView, params); 
    adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, list); 
    listView.setAdapter(adapter); 
    
    final Handler handler = new Handler(); 
    Timer timer = new Timer(); 
    TimerTask doAsynchronousTask = new TimerTask() { 
    @Override 
    public void run() { 
    handler.post(new Runnable() { 
    public void run() { 
    try { 
    dis=new DispAsync(); 
    dis.execute(); 
    } catch (Exception e) { 
    } 
    } 
    }); 
    } 
    }; 
    timer.schedule(doAsynchronousTask, 0, 7000); //execute in every 70000 ms 
    return super.onStartCommand(intent, flags, startId); 
    } 
    
    public class DispAsync extends AsyncTask<Void, Void, String> 
    { 
    @Override 
    protected void onPreExecute() { 
    list.clear(); 
    super.onPreExecute(); 
    } 
    
    @Override 
    protected String doInBackground(Void... params) { 
    
    String line = null; 
    try 
    { 
    line = dynamic data; 
    while (line != null) { 
    if(line.contains("com")) 
    {list.add(line);} 
    line = reader.readLine(); 
    i++; 
    } 
    
    p.waitFor(); 
    } 
    catch(Exception e){} 
    return line; 
    } 
    
    @Override 
    protected void onPostExecute(String result) { 
    
    adapter.notifyDataSetChanged(); 
    super.onPostExecute(result); 
    } 
    
    } 
    @Override 
    public void onDestroy() { 
    super.onDestroy(); 
    if (overlayedButton != null) { 
    wm.removeView(overlayedButton); 
    wm.removeView(topLeftView); 
    overlayedButton = null; 
    topLeftView = null; 
    } 
    } 
    
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
    
    if (event.getAction() == MotionEvent.ACTION_DOWN) { 
    float x = event.getRawX(); 
    float y = event.getRawY(); 
    
    moving = false; 
    
    int[] location = new int[2]; 
    overlayedButton.getLocationOnScreen(location); 
    
    originalXPos = location[0]; 
    originalYPos = location[1]; 
    
    offsetX = originalXPos - x; 
    offsetY = originalYPos - y; 
    
    } else if (event.getAction() == MotionEvent.ACTION_MOVE) { 
    int[] topLeftLocationOnScreen = new int[2]; 
    topLeftView.getLocationOnScreen(topLeftLocationOnScreen); 
    
    System.out.println("topLeftY="+topLeftLocationOnScreen[1]); 
    System.out.println("originalY="+originalYPos); 
    
    float x = event.getRawX(); 
    float y = event.getRawY(); 
    
    WindowManager.LayoutParams params = (LayoutParams) overlayedButton.getLayoutParams(); 
    
    int newX = (int) (offsetX + x); 
    int newY = (int) (offsetY + y); 
    
    if (Math.abs(newX - originalXPos) < 1 && Math.abs(newY - originalYPos) < 1 && !moving) { 
    return false; 
    } 
    
    params.x = newX - (topLeftLocationOnScreen[0]); 
    params.y = newY - (topLeftLocationOnScreen[1]); 
    
    wm.updateViewLayout(overlayedButton, params); 
    moving = true; 
    } else if (event.getAction() == MotionEvent.ACTION_UP) { 
    if (moving) { 
    return true; 
    } 
    } 
    
    return false; 
    } 
    
    @Override 
    public void onClick(View v) { 
    Toast.makeText(this, "Overlay button click event", Toast.LENGTH_SHORT).show(); 
    } 
    }