Search code examples
androidmultithreadingobjectshared

How to share an object between threads


Recently I started working on a home monitoring system. I'm using and arduino to read the sensor data (like temperature) and send it to the raspberry pi over a serial port. On the raspberry pi I'm running a a java TCP server which reads the serial data and sends it to the clients (format: temperature:light). This all works perfectly fine, so yesterday I began developing an android app that connects to the server and display the data. This part also works pretty well. But I ran into a problem when I tried to make a widget. Because I need to update the TextViews every 1 sec (or whenever the data is received) I store the RemoteViews, AppWidgetManager and the int[] appWidgetIds in some private variables which get refreshed everytime the onUpdate() method is called. The problem is that the variables have a value, but when I try to use them iside of a new thread created by the startListener() method I get a NullPointerException.

Here's the code:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.util.Log;
import android.widget.RemoteViews;

public class WidgetActivity extends AppWidgetProvider {

private volatile RemoteViews views;
private volatile AppWidgetManager manager;
private volatile int[] ids;
private volatile Thread listener;
private volatile boolean running = false;
private volatile Socket s;
private volatile BufferedReader br;

public void onEnabled(Context context){
    startListener();
}

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
    views = new RemoteViews(context.getPackageName(), R.layout.activity_widget);
    Log.d("Views1", views.toString());
    manager = appWidgetManager;
    Log.d("Manager1", manager.toString());
    ids = appWidgetIds;
    Log.d("IDS1", ids.toString());
    startListener();
}

public void onDisabled(Context context){
    running = false;
    if(listener != null){
        listener.interrupt();
    }
    listener = null;
    try {
        if(br != null){
            br.close();
        }
        if(s != null){
            s.close();
        }
    } catch (IOException e) {
    }
}

public void startListener(){
    if(listener == null || !listener.isAlive() || !running){
        listener = new Thread(){
            public void run(){
                synchronized(views){
                    synchronized(ids){
                        synchronized(manager){
                try {
                    s = new Socket("000.000.000.000", 7777);
                    br = new BufferedReader(new InputStreamReader(s.getInputStream()));
                    running = true;
                    while(running && !this.isInterrupted()){
                        String data = br.readLine();
                        if(data != null && data.contains(":")){
                            String[] split = data.split(":");
                            if(views != null){
                                views.setTextViewText(R.id.tempWidget, "Temperature: " + split[0]);
                                views.setTextViewText(R.id.lightWidget, "Light: " + split[1]);
                            }else{
                                Log.d("Views", "NULL!");
                            }
                            if(ids != null && manager != null){
                                for(int id : ids){
                                    manager.updateAppWidget(id, views);
                                }
                            }else{
                                Log.d("IDS", "NULL!");
                                Log.d("Manager", "NULL!");
                            }
                        }
                    }
                    if(br != null){
                        br.close();
                    }
                    if(s != null){
                        s.close();
                    }
                    listener = null;
                } catch (UnknownHostException e) {
                } catch (IOException e) {
                }
            }
            }
        }
            }
        };
        listener.start();
    }
}
}

I'm pretty new to android and this piece of code is just to test the communication and to start learning a bit more about android. I'm going to rebuild the whole app and make the code much nicer after I get this working.

Thank you for help :)

I tried all sorts of stuff already, like the synchronized blocks and volatile modifier... Nothing seems to be working...


Solution

  • Does running stuff on the UI thread helps you..

    public void startListener(){
        if(listener == null || !listener.isAlive() || !running){
    
            listener = new Thread(){
    
                public void run(){
    
                    Handler mHandler = new Handler();
    
                    mHandler.post(new Runnable(){
                        public void run() {
    
                            //try here
    
                        }
                    });