I am writing a piece of code for my Android Phone which will create a list of WifiDevices in the area using its personal scan.
I am getting java.lang.NullPointerException when I am creating a list.
My code goes follows:
public static synchronized void addDevice(DeviceInformation device, View v, Context con, boolean bool, int type) throws IOException {
Log.v("addDevice", "Called");
if (bool) {
TableLayout tb = (TableLayout) v.findViewById(R.id.DeviceList);
LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
TableRow tr = new TableRow(con);
TextView tv = new TextView(con);
System.out.println(v.toString());
tv.setLayoutParams(layout);
tr.setLayoutParams(layout);
String message;
Log.v("addDevice","Device Timeout");
switch(type) {
case 1:
computerEnd = true;
break;
case 2:
raspberryEnd = true;
break;
case 3:
flyportEnd = true;
break;
}
if (computerEnd && raspberryEnd && flyportEnd) {
if (rowCounter > 0) {
message = "No More Devices";
} else {
message = "No Devices Found";
}
tv.setText(message);
tv.setTextColor(Color.WHITE);
if (rowCounter % 2 == 0) {
tr.setBackgroundColor(Color.DKGRAY);
} else {
tr.setBackgroundColor(Color.GRAY);
}
tv.setVisibility(1);
tr.addView(tv);
tb.addView(tr); //This is line number 131
}
} else {
TableLayout tb = (TableLayout) v.findViewById(R.id.DeviceList);
LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
TableRow tr = new TableRow(con);
TextView tv = new TextView(con);
tv.setLayoutParams(layout);
tr.setLayoutParams(layout);
Log.v("addDevice", "Received");
String textToDisplay = device.getDeviceTypeString() + "\n" + device.getIPAddress(); //Write the text to display
tv.setText(textToDisplay);
tv.setTextColor(Color.WHITE);
Drawable img;
if (device.getDeviceType() == 1) {
img = con.getResources().getDrawable(R.drawable.pc);
} else if (device.getDeviceType() == 2) {
img = con.getResources().getDrawable(R.drawable.raspberry);
} else {
img = con.getResources().getDrawable(R.drawable.flyport);
}
img.setBounds(0,0,70,45);
tv.setCompoundDrawables(null, null, img, null);
tv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//empty
}
});
if (rowCounter % 2 == 0) {
tr.setBackgroundColor(Color.DKGRAY);
} else {
tr.setBackgroundColor(Color.GRAY);
}
rowCounter++;
Log.v("Result", "Device Added");
}
}
My Logcat error:
05-11 05:25:07.500: E/AndroidRuntime(30710): FATAL EXCEPTION: Thread-20873
05-11 05:25:07.500: E/AndroidRuntime(30710): java.lang.NullPointerException
05-11 05:25:07.500: E/AndroidRuntime(30710): at com.example.devicecontrolpanel.DeviceManagerWindow.addDevice(DeviceManagerWindow.java:131)
05-11 05:25:07.500: E/AndroidRuntime(30710): at com.connection.NetworkScanListenerRaspberry.run(NetworkScanListenerRaspberry.java:62)
05-11 05:25:07.500: E/AndroidRuntime(30710): at java.lang.Thread.run(Thread.java:864)
This is how this particular code is reached:
This code calls a Thread which in return calls this method.
public void searchDevice(View view) throws IOException, InterruptedException
{
try
{
Thread ComputerListener = new Thread(new NetworkScanListenerComputer(getApplicationContext(),view));
ComputerListener.start();
}
catch(Exception e)
{
Log.v("Exception:","Exception from SearchDevice Method"+e.toString());
}
}
This the code for the Thread:
package com.connection;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import android.content.Context;
import android.util.Log;
import android.view.View;
import com.example.devicecontrolpanel.DeviceManagerWindow;
public class NetworkScanListenerComputer implements Runnable
{
View thisView;
Context thisContext;
MulticastSocket socket = null;
DatagramPacket inPacket = null;
byte[] inBuf;
public NetworkScanListenerComputer(Context con, View v)
{
thisView = v;
thisContext = con;
try
{
socket = new MulticastSocket(WifiConstants.COMPUTER_RECV_PORT);
socket.joinGroup(InetAddress.getByName(WifiConstants.COMPUTER_NETWORK_ADDR));
inBuf = new byte[1024];
inPacket = new DatagramPacket(inBuf, inBuf.length);
socket.setSoTimeout(1*60*1000);
}
catch(Exception ioe)
{
Log.v("Exeception:","Computer Listener Exception"+ioe);
}
}
#Override
public void run()
{
try
{
while(true)
{
System.out.println("Listening...");
socket.receive(inPacket);
System.out.println("Received");
String msg = new String(inBuf, 0, inPacket.getLength());
DeviceInformation device = new DeviceInformation(1, msg, inPacket.getAddress().toString());
DeviceManagerWindow.addDevice(device, thisView, thisContext, false, 1);
Log.v("Received:","Received Computer From :" + inPacket.getAddress() + " Msg : " + msg);
//System.out.write(inPacket.getData(),0,inPacket.getLength());
System.out.println();
Thread.sleep(2000);
}
}
catch(Exception e)
{
Log.v("Exception:","During Receiving Computer: "+e.toString());
try
{
DeviceManagerWindow.addDevice(null, thisView, thisContext, true, 1);
}
catch (IOException e1)
{
Log.v("Exception:", "Computer End Error: " +e1);
}
}
finally
{
socket.close();
}
}
}
I am passing the view and the context of the application which is again redirected to the static method because static method cannot make use of them.
I figured out the problem... it is saying.. Only the original thread that created a view hierarchy can touch its views.
That is the thread (DeviceManagerWindow.java) which created the view can only access R.id.deviceList. So what should I do if I want to access it.?
The problem appears to be that you are trying to update the UI from a background Thread. You could use runOnUiThread() but even easier I think would be to make that Thread an AsyncTask. Then you can do all of the network stuff in the doInBacground() and update the UI in onPostExecute()
If this is a separate file and not an inner class then you can just pass context to the constructor so you can update the UI. Or you can return a value which tells the calling Activity to do something or not. I'm not sure but it looks like you might be calling this one at a time. If so, I would suggest calling a task to get all of the devices in the background while the UI is doing something and add them to a list from there. The other thing is it looks like you may have an infinite loop with while true in your Thread. If this is the case, I would change that to something that listens for a value to change. Hope this helps
Well, the first thing you should do is debugging, to get exactly where is your null pointer exception. But if you take a good look at your code, then there are two very probable possibilities for having a null pointer exception, the first one could be:
TableLayout tb = (TableLayout) v.findViewById(R.id.DeviceList);
because View v didn't found any view with id == "DeviceList"
or here:
if(device.getDeviceType()==1)
because device is getting passed in your method "null".
So, check out these two.
Good Luck
Related
In my application i should used socket.io and i want when receive my event update UI elements!
I write below codes and i receive my events show me logs, but not update any UI!
I want when receive event, check this winner is user or not and then update my UI.
In logCat show me my logs but not update any UI elements!
My codes:
public void onsocketFinishRecieve(final JSONObject ob) {
try {
((BaseActivity) context).runOnUiThread(() -> {
try {
cancelTimer();
final FinishResponse finishResponse = new Gson().fromJson(ob.toString(), FinishResponse.class);
if (finishResponse.getRes().getWinnerName().equals("not user") || finishResponse.getRes().getWinnerName().equals("not winner")) {
winnerNameWhenFinished = "Not winner";
} else {
winnerNameWhenFinished = finishResponse.getRes().getWinnerName();
}
if (detail.getId() != null) {
if (detail.getId() == finishResponse.getRes().getId()) {
//Set new winner layouts
//Register in auction
if (Constants.profileResponse != null) {
if (Constants.profileResponse.getRes() != null) {
if (Constants.profileResponse.getRes().getUser() != null) {
//Winner
if (Constants.profileResponse.getRes().getUser().getId().equals(finishResponse.getRes().getUserId())) {
Log.e("FinishedSocket", "1");
detailPage_bottomWinnerRateTxt.setVisibility(View.GONE);
detailPage_bottomWinnerBuyTxt.setText("Show basket");
detailPage_bottomWinnerBuyTxt.setOnClickListener(v -> {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra("OPEN_CART_IN_MAIN", "true");
startActivity(intent);
});
} else {
Log.e("FinishedSocket", "2");
//Loser
detailPage_bottomWinnerBuyTxt.setText("Awesome offers");
}
}
}
}
}
}
} catch (Exception e) {
Log.e("DetailResErr", e.getMessage());
}
});
} catch (Exception e) {
Log.e("DetailResErr", e.getMessage());
}
}
Logcat message :
2020-03-08 13:37:37.399 E/FinishedSocket: 2
In logcat show me above message , why not run this line : detailPage_bottomWinnerBuyTxt.setText("Awesome offers"); ??
How can i fix it?
try to run this on Mainthread like this.
someActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
//Your code to run in GUI thread here
detailPage_bottomWinnerBuyTxt.setText("Awesome offers");
}
});
Sockets work on IOThread while other side UI Work on separate Thread called UI thread. So, update the UI element on UI Thread.
Use Annotation :
#UiThread
public abstract void setText(#NonNull String text) { ... }
For know about more annotation, Check the following blog:
https://medium.com/#gurwindersingh_37022/android-annotations-30b4a2850d0
I want to send value from string (distance to obstacle) to my TextView in main activity.
I tried to use Handler, but still not working (crash) or receive nothing.
A part code which receive data from HC-05 (screen where you see in debug value assignet to variable)
enter image description here
#Override
public void run() {
byte[] buffer = new byte[1024];
int bytes;
while(true){
try {
bytes = inputStream.read(buffer);
final String comingMsg = new String(buffer,0,bytes);
Log.d(TAG,"InputStream: " + comingMsg);
/*mHandler2.post(new Runnable() {
#Override
public void run() {
Message message = new Message();
message.obj = comingMsg;
mHandler2.sendMessage(message);
}
});*/
}catch (IOException e){
Log.e(TAG,"Write: Error reading input." + e.getMessage());
active=false;
break;
}
}
}
Here It's parts of code from MainActivity where I tried put something to get values from service.
[I add, that for this moment i want to see something values from bluetooth in textView. Later I want to create parse string and send custom text to custom TextView - example: FL: (Front Left)- to one textView, FR: (Front Right) - to second textView]
There is method implementThreads(), because I wanted to do 6 Threads to 6 TextView which every time is refreshing value from string in Services (there I tried get value from Bluetooth Service)
Log.d(TAG,"Check intent - result");
if(getIntent().getIntExtra("result",0)==RESULT_OK){
mDevice = getIntent().getExtras().getParcelable("bonded device");
myBluetoothService = new MyBluetoothService(getApplicationContext());
startConnection(mDevice,MY_UUID);
Log.d(TAG,"Check is active service");
checkIfActive();
}
Log.d(TAG,"Check intent - connect_to_paired");
if(getIntent().getIntExtra("connect_to_paired",0)==RESULT_OK){
mDevice = getIntent().getExtras().getParcelable("bonded_paired_device");
myBluetoothService = new MyBluetoothService(getApplicationContext());
startConnection(mDevice,MY_UUID);
Log.d(TAG,"Check is active service");
checkIfActive();
}
}
#Override
public void onStart(){
super.onStart();
myBluetoothService = new MyBluetoothService(getApplicationContext());
}
public void checkIfActive(){
Log.d(TAG,"CheckIfActive: Started");
if(myBluetoothService.active){
Log.d(TAG,"CheckIfActive: Running method implementThreads()");
implementThreads();
}
}
public void implementThreads(){
Log.d(TAG,"ImplementThreads: Started");
Thread thread = new Thread(){
#Override
public void run() {
try{
sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
}
};
thread.start();
}
public void startConnection(BluetoothDevice device,UUID uuid){
Log.d(TAG,"StartConnection: Initializing connection");
myBluetoothService.startClient(device,uuid);
}
Thanks all for help, because It's very important for me !
Use this to interect with UI Thread for operations like updating textviews etc.
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
//YOUR CODE HERE
Message message = new Message();
message.obj = comingMsg;
mHandler2.sendMessage(message);
}
});
I wrote a JSoup HTML scraping class for my Android project. This custom class puts the user-inputted zip code into the constructor, and would parse that HTML. It works in an asynchronous thread from my main thread. Since there is no right way to deal with incorrect zip codes, I had check for null in a particular element, specifically:
if(doc.select("div.columns").first().text() == null)
{
((Activity) context).runOnUiThread(new Runnable() {
public void run()
{
Toast toast = Toast.makeText(context, R.string.toast_parse_fail, Toast.LENGTH_LONG);
toast.show();
return;
}
});
}
If that particular element is null (meaning that no such data exists for this zip code), it would create a toast to the user. As to why try wouldn't work in this case, it is because JSoup and Java doesn't know whether the parse failed or not, since the web page still loads fine; only, there is no data, which would crash the app from a NullPointerException from the code following it.
Despite my Toast exception handling using .runOnUiThread, my app would still crash. Is there any particular methods that would cancel the operations that follow my null-checking method? I know I am crashing because Toast is not cancelling my operations, and is preceding to execute the following code which causes my NullPointerExceptions.
Posted is my full Pollen constructor.
public Pollen(int zipcode, final Context context)
{
this.context = context;
this.zipcode = zipcode;
Document doc;
try
{
// pass address to Wunderground's website using our inputted zipcode
doc = Jsoup.connect("http://www.wunderground.com/DisplayPollen.asp?Zipcode=" + this.zipcode).get();
if(doc.select("div.columns").first().text() == null)
{
((Activity) context).runOnUiThread(new Runnable() {
public void run()
{
Toast toast = Toast.makeText(context, R.string.toast_parse_fail, Toast.LENGTH_LONG);
toast.show();
return;
}
});
}
// get "location" from XML
Element location = doc.select("div.columns").first();
this.location = location.text();
// get "pollen type" from XML
Element pollenType = doc.select("div.panel h3").first();
this.pollenType = pollenType.text();
SimpleDateFormat format = new SimpleDateFormat("EEE MMMM dd, yyyy");
// add the four items of pollen and dates
// to its respective list
for(int i = 0; i < 4; i++)
{
Element dates = doc.select("td.text-center.even-four").get(i);
Element levels = doc.select("td.levels").get(i);
try
{
pollenMap.put(format.parse(dates.text()), levels.text());
}
catch (ParseException e)
{
((Activity) context).runOnUiThread(new Runnable() {
public void run()
{
Toast toast = Toast.makeText(context, R.string.toast_parse_fail, Toast.LENGTH_LONG);
toast.show();
return;
}
});
}
}
}
catch (IOException e)
{
((Activity) context).runOnUiThread(new Runnable() {
public void run()
{
Toast toast = Toast.makeText(context, R.string.toast_parse_fail, Toast.LENGTH_LONG);
toast.show();
return;
}
});
}
}
tl;dr I still want the Toast to show - but I want on-Toast, to cancel all operations that follow it, since I know that if this particular Toast shows, if the code following it executes, it would crash the app.
Since you already in a try-catch-block, can't you just throw an exception?
public Pollen(int zipcode, final Context context) {
this.context = context;
this.zipcode = zipcode;
Document doc;
try {
// pass address to Wunderground's website using our inputted zipcode
doc = Jsoup.connect("http://www.wunderground.com/DisplayPollen.asp?Zipcode=" + this.zipcode).get();
if(doc.select("div.columns").first().text() == null) {
// Oh no! div.colums is empty. Lets throw an exception, which
// will prevent the code below from executing.
throw new IllegalStateException("div.columns is NULL");
}
// get "location" from XML
Element location = doc.select("div.columns").first();
this.location = location.text();
// get "pollen type" from XML
Element pollenType = doc.select("div.panel h3").first();
this.pollenType = pollenType.text();
SimpleDateFormat format = new SimpleDateFormat("EEE MMMM dd, yyyy");
// add the four items of pollen and dates
// to its respective list
for(int i = 0; i < 4; i++) {
Element dates = doc.select("td.text-center.even-four").get(i);
Element levels = doc.select("td.levels").get(i);
// Removed nested try-catch block
pollenMap.put(format.parse(dates.text()), levels.text());
}
} catch (IOException e) {
displayToast(context);
} catch (ParseException e) {
// We catch the ParseException here instead of nesting try-catch blocks.
displayToast(context);
} catch (IllegalStateException e) {
// Catch the IllegalStateException thrown when div.columns was null,
// and let the user know what went wrong.
displayToast(context);
}
}
private void displayToast(Context context) {
((Activity) context).runOnUiThread(new Runnable() {
public void run() {
Toast toast = Toast.makeText(context, R.string.toast_parse_fail, Toast.LENGTH_LONG);
toast.show();
}
});
}
I have to do a big task while a button click in my android app so i am using runnable to do background work. My works fine without the use of runnable but big task freezes it for a while. After the use of runnable my app is getting crashed on button click.
Here is my code for button onClick function:
public void doSearch(View v)
{
EditText et1 = (EditText) findViewById(R.id.searchText);
String query = et1.getText().toString();
Toast.makeText(this, "Searching Lyrics for "+query, Toast.LENGTH_LONG).show();
final String query1 = query.replaceAll(" ", "+");
Runnable myRunnable = new Runnable() {
#Override
public void run(){
try{
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://example.com/search.php?q="+query1);
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
String line = null;
int count=0,counter=0, disCount=0;
String[] name = new String[20];
String[] link = new String[20];
String[] dis = new String[20];
while ((line = reader.readLine()) != null && counter<20){
if(count == 1){
if(line.contains("href=\"")){
line = line.substring(line.indexOf('=')+2);
link[counter] = line.substring(0, line.indexOf('"'));
line = line.substring(line.indexOf('"')+2);
name[counter] = line.substring(0, line.indexOf('<'));
}
if(disCount==1){
if(line.contains("<b>")){
line = line.replaceAll("<b>", "");
}
if(line.contains("</b>")){
line = line.replaceAll("</b>", "");
}
dis[counter] = line+"...";
counter++;
disCount=0;
}
}
if(line.equals("<div class=\"sen\">")){
count = 1;
}
if(line.equals("<div>")){
disCount=1;
}
if(line.equals("</div>")){
count = 0;
}
}
is.close();
line 82: searchResult(name, link, dis);
}catch(IOException e){} catch(IllegalStateException e){}
}
};
Thread myThread = new Thread(myRunnable);
myThread.start();
}
public void searchResult(String[] name, String[] link, String[] dis)
{
line 91: setContentView(R.layout.results);
nameTemp = name;
linkTemp = link;
rowItems = new ArrayList<RowItem>();
for (int i = 0; i < name.length; i++) {
if(name[i]==null) break;
if(name[0]==null){
Toast.makeText(this, "Sorry! No results matched your query. \n Try again! ", Toast.LENGTH_LONG).show();
}
RowItem item = new RowItem(name[i], dis[i]);
rowItems.add(item);
}
listView = (ListView) findViewById(R.id.result);
CustomListViewAdapter adapter = new CustomListViewAdapter(this, R.layout.list_item, rowItems);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(this, "Loading Lyrics for "+nameTemp[position]+"!", Toast.LENGTH_SHORT).show();
Intent i = new Intent(this, ShowLyricsActivity.class);
i.putExtra("link", linkTemp[position]);
startActivity(i);
}
Here is my logcat:
I/ActivityManager(15444): Starting activity: Intent { act=android.intent.action.MAIN flg=0x10100000 cmp=com.BoxscapeInc.SongLyrics/.MainActivity }
V/ActivityThread(28108): Reporting idle of ActivityRecord{4a2ccbe0 token=android.os.BinderProxy#4a2cc658 {com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity}} finished=false
I/WindowManager(15444): Delivering pointer 0 > Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
I/WindowManager(15444): Delivering pointer 1 > Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
I/WindowManager(15444): Dispatching key to Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
I/WindowManager(15444): Dispatching key to Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
I/WindowManager(15444): Delivering pointer 0 > Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
I/WindowManager(15444): Delivering pointer 1 > Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
E/AndroidRuntime(28108): at com.BoxscapeInc.SongLyrics.MainActivity.searchResult(MainActivity.java:92)
E/AndroidRuntime(28108): at com.BoxscapeInc.SongLyrics.MainActivity$100000000.run(MainActivity.java:82)
W/ActivityManager(15444): Force finishing activity com.BoxscapeInc.SongLyrics/.MainActivity
I/ActivityManager(15444): Process com.BoxscapeInc.SongLyrics (pid 28108) has died.
Somebody please help me with this error.
Any help or suggestions would be appreciated.
In Android you can modify UI components only from main thread. You are accessing components in searchResult method called from other thread.
You can do it that way:
et1.post(new Runnable() {
#Override
public void run() {
searchResult(...);
}
});
It will force you to make some variables final, so you can use them in anonymous object. It is OK. See post method.
Personally I would recommend you using AsyncTask class instead of raw Java thread. It composes running one method in background thread and running another method in main thread.
Instead of doing network calls like you have done , I suggest you use this library
you can have a look at here
http://loopj.com/android-async-http/
your code will become very very less , instead of declaring so may asynctask seperately writing bulk of code , you can just use 4 lines of code
AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
System.out.println(response);
}
});
It is very efficient in getting the response very quickly in 2 secs.
you don't need to use buffer reader or stuff to format the response. You can directly use the response recieved in string "response" of onSucces method.
I hope this will help you out. :)
Similar or the same Question has been answered here
I am creating an Android App, which sends a broadcast message to the network and prepares a list of devices responding back.
Now What I did:
I created an Activity Class DeviceManagerWindow.java which calls a thread Sender.java.
Sender.java is responsible for sending the broadcast message.
Then the DeviceManagerWindow.java calls another thread which is responsible for listening to the devices responding back. The devices responding back will be listed in the Activity as soon as the device responds back. For that I have a TableLayout named deviceList.
What code I have written:
DeviceManagerWindow.java This method is called when a button for search is pressed
public void searchDevice(View v) throws IOException, InterruptedException
{
//Log.v("TableLayout:",view.toString());
sendMulticastFlyport = new Thread(new FlyportSender(MAC));
sendMulticastFlyport.start();
new Thread()
{
public void run()
{
MulticastSocket socketComputer=null;
try
{
socketComputer = new MulticastSocket(WifiConstants.COMPUTER_RECV_PORT);
socketComputer.joinGroup(InetAddress.getByName(WifiConstants.COMPUTER_NETWORK_ADDR));
socketComputer.setSoTimeout(1*60*1000);
byte[] inBufComputer = new byte[1024];
DatagramPacket inPacketComputer = new DatagramPacket(inBufComputer, inBufComputer.length);
while(true)
{
System.out.println("Listening...");
socketComputer.receive(inPacketComputer);
System.out.println("Received");
String msg = new String(inBufComputer, 0, inPacketComputer.getLength());
DeviceInformation device = new DeviceInformation(1, msg, inPacketComputer.getAddress().toString());
addDevice(device, false, 1);
Log.v("Received:","Received Computer From :" + inPacketComputer.getAddress() + " Msg : " + msg);
//System.out.write(inPacket.getData(),0,inPacket.getLength());
System.out.println();
Thread.sleep(2000);
}
}
catch(Exception e)
{
Log.v("Exception:","During Receiving Computer: "+e.toString());
try
{
addDevice(null, true, 1);
}
catch (IOException e1)
{
Log.v("Exception:", "Computer End Error: " +e1);
}
}
finally
{
socketComputer.close();
}
}
}.start();
The following code creates a list:
public void addDevice(DeviceInformation device, boolean bool, int type) throws IOException
{
TableLayout tb = (TableLayout) findViewById(R.id.DeviceList);
Log.v("addDevice","Called");
if(bool)
{
LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
TableRow tr = new TableRow(getApplicationContext());
TextView tv = new TextView(getApplicationContext());
System.out.println(tb);
tv.setLayoutParams(layout);
tr.setLayoutParams(layout);
String message;
Log.v("addDevice","Device Timeout");
switch(type)
{
case 1:
computerEnd=true;
break;
case 2:
raspberryEnd=true;
break;
case 3:
flyportEnd=true;
break;
}
if(computerEnd && raspberryEnd && flyportEnd)
{
if(rowCounter>0)
{
message = "No More Devices";
}
else
{
message = "No Devices Found";
}
tv.setText(message);
tv.setTextColor(Color.WHITE);
if(rowCounter%2==0)
{
tr.setBackgroundColor(Color.DKGRAY);
}
else
{
tr.setBackgroundColor(Color.GRAY);
}
tv.setVisibility(1);
tr.addView(tv);
tb.addView(tr);
}
}
else
{
LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
TableRow tr = new TableRow(getApplicationContext());
TextView tv = new TextView(getApplicationContext());
tv.setLayoutParams(layout);
tr.setLayoutParams(layout);
Log.v("addDevice","Received");
String textToDisplay = device.getDeviceTypeString()+"\n"+device.getIPAddress(); //Write the text to display
tv.setText(textToDisplay);
tv.setTextColor(Color.WHITE);
Drawable img;
if(device.getDeviceType()==1)
{
img = getApplicationContext().getResources().getDrawable(R.drawable.pc);
}
else if(device.getDeviceType()==2)
{
img = getApplicationContext().getResources().getDrawable(R.drawable.raspberry);
}
else
{
img = getApplicationContext().getResources().getDrawable(R.drawable.flyport);
}
img.setBounds(0,0,70,45);
tv.setCompoundDrawables(null, null, img, null);
tv.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
}
});
if(rowCounter%2==0)
{
tr.setBackgroundColor(Color.DKGRAY);
}
else
{
tr.setBackgroundColor(Color.GRAY);
}
rowCounter++;
Log.v("Result","Device Added");
}
}
Now it is showing me an error in the logCat as:
05-11 22:01:10.165: E/AndroidRuntime(13873): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
What I have figured out from this is only the UIThread is allowed to access the Views that is created.
Previously I had tried:
new Thread()
{
public void run()
{
runOnUiThread(){
MulticastSocket socketComputer=null;
try
{
....
....
....
}
}
And that time I received an error:
Main thread cannot access Network
Before that I had tried to use synchronized methods which was called from the Receiving.java Thread File. but It also gave an error of not creating the list.
I have tried all possible ways.
Now what whould I do.?
You figured it out right. Now you can learn to either use a Handler to pass information to the UI thread (see http://www.techotopia.com/index.php/A_Basic_Overview_of_Android_Threads_and_Thread_handlers) or AsyncTask (see http://developer.android.com/reference/android/os/AsyncTask.html).
I personally prefer AsyncTask. You can paste the code which performs the search into the doInBackground() method (not need to use a separate thread, doInBackground() already does that for you) and paste the UI-related code (the list creation code) into the onPostExecute() method. Search for further examples of AsyncTask if it is not sufficiently clear how it works from the link.
EDIT: If you intend your device search code to run indefinitely, then you have to resort to Handler, as AsyncTask expects the doInBackground() method to finish before running onPostExecute(). See which option better suits your needs.