0

I need to refresh Main Activity when my Bind Service changes its state. Code for my MainActivity :

    public class MainActivity extends AppCompatActivity
        implements UDPService.OnHeadlineSelectedListener{
      protected void onStart() {
         super.onStart();
         Intent intent = new Intent(this, UDPService.class);
         bindService(intent, myConnection, Context.BIND_AUTO_CREATE);
         //startService(intent);
     }
      private ServiceConnection myConnection = new ServiceConnection() {
            public void onServiceConnected(ComponentName className, IBinder service) {
                // This is called when the connection with the service has been
                // established, giving us the object we can use to
                // interact with the service.  We are communicating with the
                // service using a Messenger, so here we get a client-side
                // representation of that from the raw IBinder object.
                UDPService.MyLocalBinder binder = (UDPService.MyLocalBinder) service;
                myService = binder.getService();
            }
            public void onServiceDisconnected(ComponentName className) {
                // This is called when the connection with the service has been
                // unexpectedly disconnected -- that is, its process crashed.
                myService = null;
            }
        };

       protected void onCreate(Bundle savedInstanceState) {
         ... //In this part i have initialized BaseAdaptater
       }

       public static Context getContextOfApplication() {
        return contextOfApplication;
    }



       @Override
       public void onArticleSelected(int position) {
        baseAdapter.notifyDataSetChanged();
       }
}

While the service is:

public class UDPService extends Service  {
    private final IBinder myBinder = new MyLocalBinder();
    LampManager lm = LampManager.getInstance();
    int port = 4096;
    public String URL;
    private DatagramSocket udpSocket;
    private DatagramPacket packet;
    String text;
    static boolean bol =false;
    OnHeadlineSelectedListener mCallback;
    int i=2;
    private void listenAndWaitAndThrowIntent() throws Exception {
        byte[] message = new byte[5120];
        if(udpSocket == null || udpSocket.isClosed()){
            udpSocket = new DatagramSocket(port);
        }
        packet = new DatagramPacket(message, message.length);
        //Thread.sleep(5000);
        Log.i("UDP client: ", "about to wait to receive");
        udpSocket.receive(packet);
        String text = new String(message, 0, packet.getLength());
        this.text = text;
        Log.d("Received data", text);
        packet.getPort();
        URL = packet.getAddress().toString().replace("/", "");
        Log.d("Address", String.valueOf(packet.getAddress()));
        Log.d("Port", String.valueOf(packet.getPort()));
        udpSocket.close();
    }

    Thread UDPBroadcastThread;

    void startListenForUDPBroadcast(){
        UDPBroadcastThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                while (true) {
                    try {
                        listenAndWaitAndThrowIntent();
                         bol = lm.addLamp(URL,text);
                        mCallback = (OnHeadlineSelectedListener) MainActivity.getContextOfApplication();
                        mCallback.onArticleSelected(i);
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        Log.i("UDP", e.getMessage());
                    }
                }
            }
        });
        UDPBroadcastThread.start();
    }

    private void stopListen() {
        udpSocket.close();
    }




    @Override
    public void onDestroy() {
        stopListen();
    }

    /*public int onStartCommand(Intent intent, int flags, int startId){
        startListenForUDPBroadcast();
        Log.i("UDP", "Service Started");
        return START_STICKY;
    }*/
    @Override
    public void onCreate(){
        super.onCreate();
        startListenForUDPBroadcast();
    }
    @Override
    public IBinder onBind(Intent intent) {
        // We don't provide binding, so return null
        Log.i("UDP", "Service Started");
        return myBinder;
    }

    public interface OnHeadlineSelectedListener {
        void onArticleSelected(int position);
    }

    public class MyLocalBinder extends Binder {
        UDPService getService() {
            return UDPService.this;
        }
        }
}

The main Activity have a Listview, a method addLamp(URL,text) adds the Lamp to the list. I need to refresh Main Activity, when bol returns true, I call notifyDataSetChanged() to refresh the listView. The code works because when call onCreate() in the main activity, that contain notifyDataSetChanged(), to refresh list with the lamp that I created with addLamp. My problem is that the Service doesn't come out of looper. Code for addLamp is:

public class LampManager extends AppCompatActivity {


    private static final LampManager ourInstance = new LampManager();
    private List<Lamp> lista = new ArrayList();
    Context applicationContext = MainActivity.getContextOfApplication();
 public boolean addLamp(String URL, String name) throws InterruptedException{
        String ip = URL.replace("/", "");
        Log.i("UDP", "Messagio ricevuto!");
        boolean b = true;
        System.out.println(getLamps().size());
        Lamp l =null;
        try {
        for(int i=0; i<getLamps().size();i++) {
            System.out.println(getLamp(i).getURL());
            System.out.println(getLamp(i).getURL());
            char c = name.charAt(name.length()-1);
            Thread.sleep(5000);
            if (lista.get(i).getName().equals(name)) {
                b = false;
            }else if(c>='0' && c<='9' && name.contains("LAMP_"))
                b=true;
            else
                b=false;
        }
        if(b){
            System.out.println("Thread.sleep(5000)");
            l = new Lamp(URL, name);
            new TcpClient(l, applicationContext).execute();
            lista.add(l);
            return b;
        }
        }catch (Exception e){
            Log.d("ERR",e.getMessage());
        }
        return b;
    }
}

While code for lamp is:

public  class Lamp extends AppCompatActivity {
    private String name;
    private int rgb;
    private Bitmap image;;
    private int intensity;
    private Boolean state;
    public String   URL;

    //save the context recievied via constructor in a local variable
    Context applicationContext = MainActivity.getContextOfApplication();


    public Lamp( String URL, String name){
        this.name=name;
        this.URL=URL;
        SharedPreferences sh = PreferenceManager.getDefaultSharedPreferences(applicationContext);
        SharedPreferences.Editor editor = sh.edit();
        setName(name);
        editor.putString(getName()+":URL", URL);
        editor.apply();
    }
Davide
  • 7
  • 5

1 Answers1

0

Use Interfaces

first, Define a Interface on your Service class:

    // Container Activity must implement this interface
public interface OnHeadlineSelectedListener {
    public void onArticleSelected(int position);
}

Now the fragment can deliver messages to the activity by calling the onArticleSelected() method (or other methods in the interface) using the mCallback instance of the OnHeadlineSelectedListener interface.

Then, on the Activity:

public static class MainActivity extends Activity
    implements HeadlinesFragment.OnHeadlineSelectedListener{
...

public void onArticleSelected(int position) {
    // The user selected the headline of an article from the HeadlinesFragment
    // Do something here to display that article
}

}

Sucess :D

Carlos Mion
  • 37
  • 1
  • 8
  • OnHeadlineSelectedListener has need of a activity. Services haven't an activity – Davide Jan 15 '18 at 11:44
  • pls explain better – Carlos Mion Jan 15 '18 at 12:16
  • OnHeadlineSelectedListener mCallback = (OnHeadlineSelectedListener) activity; when add this line into void startListenForUDPBroadcast(), for call interface OnHeadlineSelectedListener in the looper, i have need activity. What is the activity of the service? – Davide Jan 15 '18 at 12:33
  • The main you want to update, you get a reference from it – Carlos Mion Jan 15 '18 at 13:02
  • Ok, i have create `Context applicationContext = MainActivity.getContextOfApplication();` and i have declare `mCallback = (OnHeadlineSelectedListener) applicationContext;` but i have error :"android.app.Application cannot be cast to com.polito.did2017.lampapp.UDPService$OnHeadlineSelectedListener" – Davide Jan 15 '18 at 14:47
  • pls, update the code you are using on your answer, or post it here so I can have a look :D. In this case, you really can't cast a context to OnHeadlineSelectedListener – Carlos Mion Jan 15 '18 at 15:39
  • I posted the code whit Interface in the question, thanks – Davide Jan 16 '18 at 11:02