EDIT: Added an additional error and the revision to the code i made.
I am new to java/android. I am trying to create an AlertDialog inside my SmartApp class when an event is fired in my DataRobot class. I am getting an error when doing this. The event is firing and calling the function successfully in SmartApp, but when it gets to AlertDialog alert = new AlertDialog.Builder(this).create();
the following error is printed to logcat. Does anyone know what i am doing wrong or a better way to implement what i am wanting?
Logcat error:
02-05 22:39:27.081: VERBOSE/SmartApp(281): data alert event caught
02-05 22:39:27.081: VERBOSE/SmartApp(281): inside sendalert
02-05 22:39:27.090: WARN/System.err(281): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
02-05 22:39:27.122: WARN/System.err(281): at android.os.Handler.<init>(Handler.java:121)
02-05 22:39:27.122: WARN/System.err(281): at android.app.Dialog.<init>(Dialog.java:101)
02-05 22:39:27.141: WARN/System.err(281): at android.app.AlertDialog.<init>(AlertDialog.java:63)
02-05 22:39:27.141: WARN/System.err(281): at android.app.AlertDialog.<init>(AlertDialog.java:59)
02-05 22:39:27.161: WARN/System.err(281): at android.app.AlertDialog$Builder.create(AlertDialog.java:786)
02-05 22:39:27.161: WARN/System.err(281): at cpe495.smartapp.SmartApp.sendAlert(SmartApp.java:169)
02-05 22:39:27.171: WARN/System.err(281): at cpe495.smartapp.SmartApp$3.dataAlertReceived(SmartApp.java:59)
02-05 22:39:27.201: WARN/System.err(281): at cpe495.smartapp.DataRobot.fireDataAlertEvent(DataRobot.java:96)
02-05 22:39:27.201: WARN/System.err(281): at cpe495.smartapp.DataRobot.analyzeData(DataRobot.java:32)
02-05 22:39:27.211: WARN/System.err(281): at cpe495.smartapp.SmartApp$1.dataReceivedReceived(SmartApp.java:45)
02-05 22:39:27.222: WARN/System.err(281): at cpe495.smartapp.ConnectDevice.fireDataReceivedEvent(ConnectDevice.java:71)
02-05 22:39:27.222: WARN/System.err(281): at cpe495.smartapp.ConnectDevice.run(ConnectDevice.java:42)
02-05 22:39:27.242: WARN/System.err(281): at java.lang.Thread.run(Thread.java:1096)
//my smartapp class main ui
public class SmartApp extends Activity implements OnSharedPreferenceChangeListener {
TextView smartConnectionStatus;
TextView testOutputView;
Thread cThread;
private ConnectDevice cD = new ConnectDevice();
private DataRobot dR = new DataRobot();
private DataBuilder dB = new DataBuilder();
private DataSender dS = new DataSender();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.intro);
cD.addDataReceivedListener(new DataReceivedListener() {
@Override
public void dataReceivedReceived(DataReceivedEvent event) {
// TODO Auto-generated method stub
dR.analyzeData(event.getData());
}
});
dR.addDataAlertListener(new DataAlertListener() {
@Override
public void dataAlertReceived(DataAlertEvent event) {
Log.v("SmartApp", "data alert event caught");
sendAlert();
}
});
}
/* Function for sending alerts that the user has exceeded a stress index */
public void sendAlert() {
Log.v("SmartApp", "inside sendalert");
AlertDialog alert = new AlertDialog.Builder(this).create();
Log.v("SmartApp", "after builder1");
//Vibrator vibrator;
//vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
//vibrator.vibrate(500);
alert.setMessage("Testing alert dialog...");
alert.setCancelable(false);
alert.setButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.cancel();
}
});
Log.v("SmartApp", "after builder2");
//AlertDialog alert = builder.create();
alert.setTitle("Title");
Log.v("SmartApp", "after builder3");
alert.show();
Log.v("SmartApp", "after builder4");
}
}
// datarobot class
public class DataRobot extends Activity {
/* This class is for analyzing the data */
private List _listeners = new ArrayList();
private List<DataAlertListener> _listeners2 = new ArrayList<DataAlertListener>();
private SmartDataObject data;
private int sI1;
private int sI2;
private float w1;
private float w2;
private float w3;
private int hRB;
private int hRVMin;
private int hRVMax;
public boolean analyzeData(SmartDataObject temp) {
/* Analyze the data
* Returns true if data was successfully analyzed
* Returns false if an error occurred
*/
data = temp;
if(data.getHeartRate()>290) {
fireDataAlertEvent();
}
fireDataAnalyzedEvent(data);
return true; //for now this will always return true
}
public synchronized void addDataAnalyzedListener(DataAnalyzedListener listener) {
_listeners.add(listener);
}
public synchronized void removeDataAnalyzedListener(DataAnalyzedListener listener) {
_listeners.remove(listener);
}
private synchronized void fireDataAnalyzedEvent(SmartDataObject temp) {
DataAnalyzedEvent dRE = new DataAnalyzedEvent(this, temp);
Iterator listeners = _listeners.iterator();
while(listeners.hasNext()) {
((DataAnalyzedListener)listeners.next()).dataAnalyzedReceived(dRE);
}
}
public interface DataAnalyzedListener {
public void dataAnalyzedReceived(DataAnalyzedEvent event);
}
public synchronized void addDataAlertListener(DataAlertListener listener) {
_listeners2.add(listener);
}
public synchronized void removeDataAlertListener(DataAlertListener listener) {
_listeners2.remove(listener);
}
private synchronized void fireDataAlertEvent() {
DataAlertEvent dAE = new DataAlertEvent(this);
Iterator listeners = _listeners2.iterator();
while(listeners.hasNext()) {
((DataAlertListener)listeners.next()).dataAlertReceived(dAE);
}
}
public interface DataAlertListener {
public void dataAlertReceived(DataAlertEvent event);
}
}
public class DataAlertEvent extends EventObject {
public DataAlertEvent(Object source) {
super(source);
// TODO Auto-generated constructor stub
}
}
Below is the added code after trying to fix
02-06 10:27:30.673: VERBOSE/SmartApp(276): data alert event caught
02-06 10:27:31.013: WARN/System.err(276): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
02-06 10:27:31.042: WARN/System.err(276): at android.os.Handler.<init>(Handler.java:121)
02-06 10:27:31.052: WARN/System.err(276): at android.view.ViewRoot.<init>(ViewRoot.java:231)
02-06 10:27:31.052: WARN/System.err(276): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
02-06 10:27:31.062: WARN/System.err(276): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
02-06 10:27:31.082: WARN/System.err(276): at android.view.Window$LocalWindowManager.addView(Window.java:424)
02-06 10:27:31.082: WARN/System.err(276): at android.app.Dialog.show(Dialog.java:241)
02-06 10:27:31.102: WARN/System.err(276): at cpe495.smartapp.SmartApp$4.dataAlertReceived(SmartApp.java:80)
02-06 10:27:31.102: WARN/System.err(276): at cpe495.smartapp.DataRobot.fireDataAlertEvent(DataRobot.java:96)
02-06 10:27:31.122: WARN/System.err(276): at cpe495.smartapp.DataRobot.analyzeData(DataRobot.java:32)
02-06 10:27:31.122: WARN/System.err(276): at cpe495.smartapp.SmartApp$2.dataReceivedReceived(SmartApp.java:66)
02-06 10:27:31.133: WARN/System.err(276): at cpe495.smartapp.ConnectDevice.fireDataReceivedEvent(ConnectDevice.java:71)
02-06 10:27:31.133: WARN/System.err(276): at cpe495.smartapp.ConnectDevice.run(ConnectDevice.java:42)
02-06 10:27:31.153: WARN/System.err(276): at java.lang.Thread.run(Thread.java:1096)
public class SmartApp extends Activity implements OnSharedPreferenceChangeListener {
TextView smartConnectionStatus;
TextView testOutputView;
Thread cThread;
private ConnectDevice cD = new ConnectDevice();
private DataRobot dR = new DataRobot();
private DataBuilder dB = new DataBuilder();
private DataSender dS = new DataSender();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.intro);
final AlertDialog alert = new AlertDialog.Builder(this).create();
Log.v("SmartApp", "inside sendalert");
//AlertDialog alert = new AlertDialog.Builder(this).create();
Log.v("SmartApp", "after builder1");
//Vibrator vibrator;
//vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
//vibrator.vibrate(500);
alert.setMessage("Testing alert dialog...");
alert.setCancelable(false);
alert.setButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.cancel();
}
});
Log.v("SmartApp", "after builder2");
//AlertDialog alert = builder.create();
alert.setTitle("Title");
cD.addDataReceivedListener(new DataReceivedListener() {
@Override
public void dataReceivedReceived(DataReceivedEvent event) {
// TODO Auto-generated method stub
dR.analyzeData(event.getData());
}
});
dR.addDataAlertListener(new DataAlertListener() {
@Override
public void dataAlertReceived(DataAlertEvent event) {
Log.v("SmartApp", "data alert event caught");
sendAlert();
alert.show();
}
});
}
}
You must create and show alert dialog in UI thread or:
Create a Handler in UI thread.
Handler mHandler = new Handler();
Create a thread
class A implements Runnable {
public void run() {
// create and show alert here
}
}
When event is fired, call:
A a = new A();
mHandler.post(a);