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();
}
Use Interfaces
first, Define a Interface on your Service class:
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:
}
Sucess :D