I'm trying to come up with an android client app that talks with a C#server. I want to update my TextView simultaneously with the server reply message. I'm receiving message with this code
public class LogedInActivity extends ActionBarActivity {
private Spinner meterBrands;
private EditText sayacNo,plcNo;
private String serverMessage="Message is";
private TextView serverStatus;
private String messageID="120";
private String messageEnd="*?/";
private Thread clientThread;
private static final int SERVERPORT = sss;
private static final String SERVER_IP = "sss";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loged_in);
serverStatus= (TextView) findViewById(R.id.serverStatus);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
}
public void sendMessage(View view) {
hideSoftKeyboard(this);
meterBrands= (Spinner) findViewById(R.id.brandsSpinner);
String temp=String.valueOf(meterBrands.getSelectedItem());
if(isValidMeterAndPLC()){
new Thread(new Runnable() {
public void run() {
connectSocket(messageToSend());
}
}).start();
} else {
new Thread(new Runnable() {
public void run() {
connectSocket("1");
}
}).start();
}
}
private String connectSocket(String message){
String finalText = "";
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
Log.d("TCP", "C: Connecting...");
Socket socket = new Socket(serverAddr, SERVERPORT);
PrintWriter out = null;
BufferedReader in = null;
try {
Log.d("TCP", "C: Sending: '" + message + "'");
out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.println(message);
String text = "";
while ((text = in.readLine()) != null) {
finalText += text;
serverStatus.setText(finalText);
}
Log.d("TCP", "C: Sent.");
Log.d("TCP", "C: Done.");
} catch(Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
socket.close();
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
Log.e("TCP", "C: UnknownHostException", e);
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("TCP", "C: IOException", e);
e.printStackTrace();
}
return finalText;
}
public String messageToSend(){
String infoString;
sayacNo= (EditText) findViewById(R.id.sayacNoTextBox);
plcNo= (EditText) findViewById(R.id.plcNoTextBox);
infoString= messageID+"-"+sayacNo.getText()+"-"+meterBrands.getSelectedItem().toString()+"-"+plcNo.getText()+ "-" +messageEnd+"-" ;
infoString+=checkSum(infoString);
return infoString;
}
public int checkSum(String str){
int checkSum=0;
char [] strChars= str.toCharArray();
for(int i=0;i<strChars.length;i++){
checkSum+= (int) strChars[i];
}
return checkSum;
}
public void messageDisplay(String servermessage){
serverStatus= (TextView) findViewById(R.id.serverStatus);
serverStatus.setText(servermessage);
}
private boolean isValidMeterAndPLC(){
boolean check=true;
int sayacNoInt=0;
sayacNo=(EditText) findViewById(R.id.sayacNoTextBox);
plcNo=(EditText) findViewById(R.id.plcNoTextBox);
sayacNoInt=Integer.parseInt(sayacNo.getText().toString());
if(sayacNoInt<100 || sayacNoInt>65530){
alertbox("Yanlış Sayaç Numarası","Yanlış sayaç numarası girdiniz. Lütfen tekrar deneyin.");
check=false;
}
if(plcNo.getText().toString().length()!=8){
alertbox("Yanlış PLC Numarası","Yanlış PLC numarası girdiniz. Lütfen tekrar deneyin.");
check=false;
}
return check;
}
protected void alertbox(String title, String mymessage)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
this);
// set title
alertDialogBuilder.setTitle(title);
// set dialog message
alertDialogBuilder
.setMessage(mymessage)
.setCancelable(false)
.setPositiveButton("Okay",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, close
// current activity
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_loged_in,
container, false);
return rootView;
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
hideSoftKeyboard(this);
return false;
}
/*back button override.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
alertbox("asasda","5333434");
return true;
}
return super.onKeyDown(keyCode, event);
}
*/
public static void hideSoftKeyboard(Activity activity) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
}
However, I can't update my TextView since it's in a thread
new Thread(new Runnable() {
public void run() {
connectSocket(messageToSend());
}
}).start();
Simply wrap the sentence where you update with the runOnUiThread() statement. For instance:
your_context.runOnUiThread(new Runnable() {
public void run() {
myTextView.setText("...");
}
});
Anything wrapped in the runOnUiThread() statement will actually be run in the main UI Thread, so be careful to not add some expensive operations here.
---- EDIT ----
new Thread(new Runnable() {
public void run() {
connectSocket(messageToSend());
// Do whatever you need
...
// Once you want to update your TextView...
final myTextView tv = (TextView) your_context.findViewById(R.id.myTextView);
final String myText = "whatever";
your_context.runOnUiThread(new Runnable() {
public void run() {
myTextView.setText(myText);
}
});
}
}).start();
Related
This is a "hello world" app but I can't find the solution.
This is the code on the client:
public class MainActivity extends ActionBarActivity {
HubProxy proxy;
EditText messageText;
TextView resultText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Platform.loadPlatformComponent(new AndroidPlatformComponent());
//Setup connection
String server = "http://10.0.2.2:8081/";
HubConnection connection = new HubConnection(server);
proxy = connection.createHubProxy("chatHub");
Toast.makeText(getApplicationContext(),proxy.toString(),Toast.LENGTH_SHORT).show();
resultText = (TextView) findViewById(R.id.resultText);
//Start connection
SignalRFuture<Void> awaitConnection = connection.start();
//--HERE IS WHERE I AM NOT SURE HOW TO SET IT UP TO RECEIVE A NOTIFICATION---
//Setup to receive broadcast message
proxy.on("SimpleMessage", new SubscriptionHandler1<String>() {
#Override
public void run(String s) {
resultText.setText(resultText.getText()+"\n"+s.toString());
Toast.makeText(getApplicationContext(), "message recieved: "+s.toString(), Toast.LENGTH_LONG).show();
}
}
, String.class);
proxy.on("Alert", new SubscriptionHandler() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Alert Recieved!!!", Toast.LENGTH_LONG).show();
//resultText.setText(resultText.getText()+"\nAlert Recieved!!!");
}
});
//---------------------------------------------------------------------------
proxy.subscribe(this);
try {
awaitConnection.get();
Toast.makeText(getApplicationContext(), "success", Toast.LENGTH_LONG).show();
} catch (InterruptedException e) {
Toast.makeText(getApplicationContext(), "un success", Toast.LENGTH_LONG).show();
} catch (ExecutionException e) {
Toast.makeText(getApplicationContext(), "in success: " + e.getMessage().toString(), Toast.LENGTH_LONG).show();
}
messageText = (EditText) findViewById(R.id.messageText);
Button sendBTN = (Button) findViewById(R.id.sendBTN);
sendBTN.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
String textToSend = messageText.getText().toString();
proxy.invoke("Send", "Android", textToSend ).get();
} catch (InterruptedException e) {
// Handle ...
} catch (ExecutionException e) {
// Handle ...
}
}
});
}
public void Alert(){
Toast.makeText(getApplicationContext(), "Alert Recieved!!!", Toast.LENGTH_LONG).show();
//resultText.setText(resultText.getText()+"\nAlert Recieved!!!");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
I think the mistake is in this code and therefore I do not append the code of the server and the JS client.
You can refer to my following sample code. I have tested. Hope this helps!
public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private final Context mContext = this;
private Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.textView);
mHandler = new Handler(Looper.getMainLooper());
Platform.loadPlatformComponent(new AndroidPlatformComponent());
Credentials credentials = new Credentials() {
#Override
public void prepareRequest(Request request) {
request.addHeader("User-Name", "BNK");
}
};
String serverUrl = "http://192.168.1.100/signalr";
HubConnection connection = new HubConnection(serverUrl);
connection.setCredentials(credentials);
HubProxy hubProxy = connection.createHubProxy("ChatHub");
ClientTransport clientTransport = new ServerSentEventsTransport(connection.getLogger());
SignalRFuture<Void> awaitConnection = connection.start(clientTransport);
try {
awaitConnection.get();
} catch (InterruptedException | ExecutionException e) {
Log.e("SignalR", e.toString());
e.printStackTrace();
return;
}
hubProxy.on("SimpleMessage", new SubscriptionHandler1<String>() {
#Override
public void run(final String s) {
Log.i("SignalR", s);
mHandler.post(new Runnable() {
#Override
public void run() {
mTextView.setText(mTextView.getText() + "\n" + s);
Toast.makeText(mContext, "message recieved: " + s, Toast.LENGTH_LONG).show();
}
});
}
}, String.class);
}
...
}
My goal is to create Java application which would be server, and Android(client) socket connection, and make Android phone listen to my commands send from a server. My question is, how should i make my Android phone always listen for incoming commands(Strings) pushed from Java application. What is a best choice ? Thread, Service ?
Here is my code : Server in java:
public class Server extends JFrame {
private JTextField userText;
private JTextArea chatWindow;
private ObjectOutputStream output;
private ObjectInputStream input;
// private DataInputStream input;
private Socket connection;
ServerSocket server;
public Server() {
super("GUI");
userText = new JTextField();
userText.setEditable(false);
userText.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
sendMessage(e.getActionCommand());
userText.setText("");
}
});
add(userText, BorderLayout.NORTH);
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow), BorderLayout.CENTER);
setSize(300, 150);
setVisible(true);
}
// connect to server
public void startRunning() {
try {
server = new ServerSocket(9000, 100);
while (true) {
try {
waitForConnection();
setupStreams();
whileChatting();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (EOFException e) {
showMessage("\n Connection lost");
} catch (IOException e) {
e.printStackTrace();
} finally {
closeCrap();
}
}
// connect to server
private void waitForConnection() throws IOException {
showMessage(" \nWaiting for connection \n");
connection = server.accept();
showMessage(" now connected to "
+ connection.getInetAddress().getHostName());
}
private void setupStreams() throws IOException {
showMessage("\n Setting up streams \n");
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
// input = new DataInputStream(connection.getInputStream());
input = new ObjectInputStream(connection.getInputStream());
showMessage(" Streams are good \n");
}
private void whileChatting() throws IOException {
ableToType(true);
String message = "You are now connected ";
sendMessage(message);
do {// have conversation
try {
message = (String) input.readObject();
// message = (String) input.readLine();
showMessage("\n" + message);
} catch (ClassNotFoundException e) {
showMessage("Dont know that object type ");
// TODO: handle exception
}
} while (!message.equals("server - end"));
}
// close everything
private void closeCrap() {
showMessage("\n Closing..");
ableToType(false);
try {
output.close();
input.close();
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// send message to server
private void sendMessage(String message) {
try {
output.writeObject("CLIENT - " + message);
output.flush();
showMessage("\n" + "CLIENT - " + message);
} catch (IOException e) {
chatWindow.append("\n Smth is wrong sending message");
}
}
private void showMessage(final String m) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
chatWindow.append(m);
}
});
}
private void ableToType(final boolean tof) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
userText.setEditable(tof);
}
});
}
}
Android Client code:
public class MainActivity extends ActionBarActivity {
TextView text;
Socket socket;
DataInputStream is;
DataOutputStream os;
public final String TAG = "CLIENT";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
ConnectThread thread = new ConnectThread();
thread.execute();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public class ConnectThread extends AsyncTask<String, String, String> {
public ConnectThread() {
}
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
Log.i(TAG,"Do in background");
return connect();
}
public String connect() {
try {
Log.i(TAG," creating socket");
socket = new Socket("192.168.1.10", 9000);
Log.i(TAG," socket created");
os = new DataOutputStream(socket.getOutputStream());
is = new DataInputStream(socket.getInputStream());
Log.i(TAG," Streams are set");
Log.i(TAG,"::"+is.readUTF().toString());
text.setText(is.readLine().toString());
return is.readLine().toString();
} catch (UnknownHostException e) {
e.printStackTrace();
Log.d("fail", e.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("fail", e.toString());
}
return "nothing";
}
}
}
I have solved my problem. Im sending messages from my java server to android trough a socket, and android is always listening. Here is my code:
Java :
public class Server extends JFrame {
private JTextField userText;
private JTextArea chatWindow;
private ObjectOutputStream output;
private ObjectInputStream input;
// private DataInputStream input;
private Socket connection;
ServerSocket server;
public Server() {
super("GUI");
userText = new JTextField();
userText.setEditable(false);
userText.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
sendMessage(e.getActionCommand());
userText.setText("");
}
});
add(userText, BorderLayout.NORTH);
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow), BorderLayout.CENTER);
setSize(300, 150);
setVisible(true);
}
// connect to server
public void startRunning() {
try {
server = new ServerSocket(9000, 100);
while (true) {
try {
waitForConnection();
setupStreams();
whileChatting();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (EOFException e) {
showMessage("\n Connection lost");
} catch (IOException e) {
e.printStackTrace();
} finally {
closeCrap();
}
}
// connect to server
private void waitForConnection() throws IOException {
showMessage(" \nWaiting for connection \n");
connection = server.accept();
showMessage(" now connected to "
+ connection.getInetAddress().getHostName());
}
private void setupStreams() throws IOException {
showMessage("\n Setting up streams \n");
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
// input = new DataInputStream(connection.getInputStream());
input = new ObjectInputStream(connection.getInputStream());
showMessage(" Streams are good \n");
}
private void whileChatting() throws IOException {
ableToType(true);
String message = "You are now connected ";
sendMessage(message);
do {// have conversation
try {
message = (String) input.readObject();
// message = (String) input.readLine();
showMessage("\n" + message);
} catch (ClassNotFoundException e) {
showMessage("Dont know that object type ");
// TODO: handle exception
}
} while (!message.equals("server - end"));
}
// close everything
private void closeCrap() {
showMessage("\n Closing..");
ableToType(false);
try {
output.close();
input.close();
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// send message to server
private void sendMessage(String message) {
try {
output.writeUTF("CLIENT - " + message);
output.flush();
showMessage("\n" + "CLIENT - " + message);
} catch (IOException e) {
chatWindow.append("\n Smth is wrong sending message");
}
}
private void showMessage(final String m) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
chatWindow.append(m);
}
});
}
private void ableToType(final boolean tof) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
userText.setEditable(tof);
}
});
}
}
And android :
public class MainActivity extends ActionBarActivity {
TextView text;
Socket socket;
DataInputStream is;
ObjectOutputStream os;
public final String TAG = "CLIENT";
Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
handler = new Handler();
Thread x = new Thread(new ClientThread());
x.start();
handler = new Handler();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
//
public class ClientThread implements Runnable {
public ClientThread() {
// TODO Auto-generated constructor stub
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
while (true) {
socket = new Socket("192.168.1.10", 9000);
handler.post(new Runnable() {
#Override
public void run() {
text.setText("Connected.");
try {
os = new ObjectOutputStream(socket.getOutputStream());
} catch (Exception e) {
text.setText("Output stream. smth wrong");
Log.i(TAG, "Output stream. smth wrong");
}
}
});
try {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
String line = null;
while ((line = in.readUTF()) != null) {
Log.d("ServerActivity", line);
final String mesg = line;
handler.post(new Runnable() {
#Override
public void run() {
// DO WHATEVER YOU WANT TO THE FRONT END
// THIS IS WHERE YOU CAN BE CREATIVE
text.append(mesg + "\n");
}
});
}
break;
} catch (Exception e) {
handler.post(new Runnable() {
#Override
public void run() {
text.setText("Oops. Connection interrupted. Please reconnect your phones.");
}
});
e.printStackTrace();
}
}
} catch (Exception x) {
}
}
}
}
why UDP Android just once send [Please Help]
name class MainActivity
public class MainActivity extends Activity implements
android.view.View.OnClickListener {
public static final String SERVERIP = "192.168.5.255";
public static final int SERVERPORT = 4444;
public TextView text1;
public EditText input;
public Button btn;
public boolean start;
public Handler Handler;
conntection with pc
this method on create
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text1 = (TextView) findViewById(R.id.textView1);
input = (EditText) findViewById(R.id.editText1);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(this);
start = false;
new Thread(new Server()).start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
new Thread(new Client()).start();
Handler = new Handler() {
#Override
public void handleMessage(Message msg) {
String text = (String) msg.obj;
text1.append(text);
}
};
}
this class Client
#SuppressLint("NewApi")
public class Client implements Runnable {
#Override
public void run() {
while (start == false) {
}
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
updatetrack("Client: Start connecting\n");
DatagramSocket socket = new DatagramSocket();
byte[] buf;
if (!input.getText().toString().isEmpty()) {
buf = input.getText().toString().getBytes();
} else {
buf = ("Default message").getBytes();
}
DatagramPacket packet = new DatagramPacket(buf, buf.length,
serverAddr, SERVERPORT);
updatetrack("Client: Sending ‘" + new String(buf) + "’\n");
socket.send(packet);
updatetrack("Client: Message sent\n");
updatetrack("Client: Succeed!\n");
} catch (Exception e) {
updatetrack("Client: Error!\n");
}
}
}
this class Client
public class Server implements Runnable {
#Override
public void run() {
while (start = false) {
try {
InetAddress serverAddress = InetAddress.getByName(SERVERIP);
updatetrack("nServer: Start connectingn");
DatagramSocket socket = new DatagramSocket(SERVERPORT,
serverAddress);
byte[] buffer = new byte[17];
DatagramPacket packet = new DatagramPacket(buffer,
buffer.length);
updatetrack("Server: Receivingn");
socket.receive(packet);
updatetrack("Server: Message received:"
+ new String(packet.getData()) + "'n");
updatetrack("Server : Succed!n");
} catch (Exception e) {
updatetrack("Server: Error!n" + e.getMessage());
}
}
}
}
public void updatetrack(String s) {
Message msg = new Message();
String textTochange = s;
msg.obj = textTochange;
Handler.sendMessage(msg);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (v.getId() == R.id.button1)
start = true;
}
}
if i make my class server with
while (true){
application is error
help me please ? why just once send message Thanks before
For Client class, you have nothing in the loop:
while (start == false) {
}
And then outside of it, you call send only once -- that is why it is sending only once.
socket.send(packet);
If you want to call send continuously, then one way to do is to keep it in a loop. Of course, you would need to terminate the loop once the task is done but that would be driven by your application logic.
I am having problems making my TextViews visible from another thread using the method showDisclaimer(). I have used runOnUiThread() to set the visibility of my TextViews. Basically, I want to show these views after importing the csv to the database. Can you take a look and see what I missed?
public class MainActivity extends Activity {
final static int INDEX_ACCTTYPE = 0;
final static int INDEX_ECN = 1;
final static int INDEX_TLN = 2;
final static int INDEX_SIN = 3;
final static int INDEX_MOBILE = 4;
final static int INDEX_CITY = 5;
final static int INDEX_START_DATE = 6;
final static int INDEX_START_TIME = 7;
final static int INDEX_END_DATE = 8;
final static int INDEX_END_TIME = 9;
final static int INDEX_REASON = 10;
final static int INDEX_DETAILS = 11;
DatabaseHandler db;
String str;
ProgressDialog pd;
final private String csvFile = "http://www.meralco.com.ph/pdf/pms/pms_test.csv";
final private String uploadDateFile = "http://www.meralco.com.ph/pdf/pms/UploadDate_test.txt";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView homeText1 = (TextView) findViewById(R.id.home_text1);
TextView homeText2 = (TextView) findViewById(R.id.home_text2);
TextView homeText3 = (TextView) findViewById(R.id.home_text3);
TextView homeText4 = (TextView) findViewById(R.id.home_text4);
homeText1.setVisibility(View.INVISIBLE);
homeText2.setVisibility(View.INVISIBLE);
homeText3.setVisibility(View.INVISIBLE);
homeText4.setVisibility(View.INVISIBLE);
//db = new DatabaseHandler(MainActivity.this);
if(dbExists()){
db = new DatabaseHandler(MainActivity.this);
Log.d("Count", "" + db.count());
if(!uploadDateEqualsDateInFile())
promptOptionalUpdate("There is a new schedule");
showDisclaimer();
Log.i("oncreate", "finished!");
return;
}
promptRequiredUpdate("Schedule not updated");
//showDisclaimer();
Log.i("oncreate", "finished!");
}
public void promptOptionalUpdate(String Message) {
AlertDialog.Builder builder = new AlertDialog.Builder(
this);
builder.setMessage(Message)
.setCancelable(false)
.setPositiveButton("Update Now",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.d("SHOW ALERT -->!", "update");
dropOldSchedule();
triggerDownload();
dialog.cancel();
}
})
.setNegativeButton("Later",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.d("SHOW ALERT -->!", "cancel");
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
public void dropOldSchedule(){
//TODO drop old schedule
}
public void triggerDownload() {
if (!checkInternet()) {
showAlert("An internet connection is required to perform an update, please check that you are connected to the internet");
return;
}
if(pd!=null && pd.isShowing()) pd.dismiss();
pd = ProgressDialog.show(this, "Downloading schedule",
"This may take a few minutes...", true, false);
Thread thread = new Thread(new Runnable() {
public void run() {
db = new DatabaseHandler(MainActivity.this);
db.beginTransaction();
try {
URL myURL = new URL(csvFile);
BufferedReader so = new BufferedReader(new InputStreamReader(myURL.openStream()));
while (true) {
String output = so.readLine();
if (output != null) {
String[] sched = output.split(",");
try {
db.addRow(sched[INDEX_SIN], sched[INDEX_CITY],
sched[INDEX_START_DATE], sched[INDEX_START_TIME],
sched[INDEX_END_DATE], sched[INDEX_END_TIME],
sched[INDEX_DETAILS], sched[INDEX_REASON]);
} catch (IndexOutOfBoundsException e) {
db.addRow(sched[INDEX_SIN], sched[INDEX_CITY],
sched[INDEX_START_DATE], sched[INDEX_START_TIME],
sched[INDEX_END_DATE], sched[INDEX_END_TIME],
"", sched[INDEX_REASON]);
e.printStackTrace();
}
}
else {
break;
}
}
so.close();
} catch (MalformedURLException e) {
e.printStackTrace();
db.endTransaction();
} catch (IOException e) {
e.printStackTrace();
db.endTransaction();
}
Log.d("Count", ""+db.count());
db.setTransactionSuccessful();
db.endTransaction();
runOnUiThread(new Runnable() {
public void run() {
while (!pd.isShowing());
getUploadDate();
writeUploadDateInTextFile();
showDisclaimer();
pd.dismiss();
}
});
}
});
thread.start();
//while(thread.isAlive());
Log.d("triggerDownload", "thread died, finished dl. showing disclaimer...");
}
public void getUploadDate() {
Log.d("getUploadDate", "getting upload date of schedule");
if(pd!=null && pd.isShowing()) pd.dismiss();
pd = ProgressDialog.show(this, "Getting upload date",
"This may take a few minutes...", true, false);
Thread thread = new Thread(new Runnable() {
public void run() {
try {
URL myURL = new URL(uploadDateFile);
BufferedReader so = new BufferedReader(new InputStreamReader(myURL.openStream()));
while (true) {
String output = so.readLine();
if (output != null) {
str = output;
}
else {
break;
}
}
so.close();
}
catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
while (!pd.isShowing());
pd.dismiss();
}
});
}
});
thread.start();
while (thread.isAlive());
Log.d("getUploadDate","thread died, upload date="+str);
}
public void writeUploadDateInTextFile() {
Log.d("writeUploadDateTextFile", "writing:"+str);
try {
OutputStreamWriter out = new OutputStreamWriter(openFileOutput(
"update.txt", 0));
out.write(str);
out.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
public void showDisclaimer() {
Log.d("ShowDisclaimer", "showing disclaimer");
TextView homeText1x = (TextView) findViewById(R.id.home_text1);
TextView homeText2x = (TextView) findViewById(R.id.home_text2);
TextView homeText3x = (TextView) findViewById(R.id.home_text3);
TextView homeText4x = (TextView) findViewById(R.id.home_text4);
homeText3x
.setText("You may view the schedule of pre-arranged power interruptions by clicking any of these buttons : SIN, City or Date. " +
"The schedule has been updated as of " + str
+ ". Meralco is exerting all efforts to restore electric service as scheduled." +
" The schedule, however, may change without further notice. For verification, follow-ups, or " +
"latest updates, please contact our CALL CENTER through telephone nos. 16211, " +
"fax nos. 1622-8554/1622-8556 or email address callcenter.tech.assist#meralco.com.ph.");
homeText1x.setVisibility(View.VISIBLE);
homeText2x.setVisibility(View.VISIBLE);
homeText3x.setVisibility(View.VISIBLE);
homeText4x.setVisibility(View.VISIBLE);
Log.d("ShowDisclaimer", "finished showing disclaimer");
}
public void promptRequiredUpdate(String Message) {
Log.d("required update","required!");
AlertDialog.Builder builder = new AlertDialog.Builder(
this);
builder.setMessage(Message)
.setCancelable(false)
.setPositiveButton("Update Now",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.d("SHOW ALERT -->!", "update");
triggerDownload();
dialog.cancel();
}
})
.setNegativeButton("Later",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.d("SHOW ALERT -->!", "cancel");
dialog.cancel();
finish();
}
});
AlertDialog alert = builder.create();
alert.show();
}
public boolean uploadDateEqualsDateInFile() {
Log.d("uploadDateEqualsDateInFile","comparing schedule upload dates");
getUploadDate();
try {
String recordedDate = "";
InputStream instream = openFileInput("update.txt");
if (instream != null) { // if file the available for reading
Log.d("uploadDateEqualsDateInFile","update.txt found!");
InputStreamReader inputreader = new InputStreamReader(instream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line = null;
while ((line = buffreader.readLine()) != null) {
recordedDate = line;
Log.d("uploadDateEqualsDateInFile","recorded:"+recordedDate);
}
Log.d("uploadDateEqualsDateInFile","last upload date: " + str + ", recorded:" +recordedDate);
if(str.equals(recordedDate)) return true;
return false;
}
Log.d("uploadDateEqualsDateInFile","update.txt is null!");
return false;
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
public void showAlert(String Message) {
AlertDialog.Builder builder = new AlertDialog.Builder(getBaseContext());
builder.setMessage(Message).setCancelable(false)
.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
public boolean checkInternet() {
ConnectivityManager cm = (ConnectivityManager) this
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo infos[] = cm.getAllNetworkInfo();
for (NetworkInfo info : infos)
if (info.getState() == NetworkInfo.State.CONNECTED
|| info.getState() == NetworkInfo.State.CONNECTING) {
return true;
}
return false;
}
public boolean dbExists() {
File database=getApplicationContext().getDatabasePath(DatabaseHandler.DATABASE_NAME);
if (!database.exists()) {
Log.i("Database", "Not Found");
return false;
}
Log.i("Database", "Found");
return true;
}
#Override
protected void onDestroy() {
super.onDestroy();
if (db != null) {
db.close();
}
}
#Override
protected void onPause() {
super.onPause();
if (db != null) {
db.close();
}
}
}
simplymoody, do what Chirag Raval suggested by declaring private static TextView homeText1, globally and in your onCreate initialise them. However, you should always update the UI from the main thread. But showDisclaimer() is still running on the background thread, so you could run the showDisclaimer() a couple of different ways. One would be to do what you have done in getUploadDate():
runOnUiThread(new Runnable() {
public void run() {
showDisclaimer()
}
});
Or you could use a handler:
private Handler showDisclaimerHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
homeText3x.setText("TEXT");
homeText1x.setVisibility(View.VISIBLE);
homeText2x.setVisibility(View.VISIBLE);
homeText3x.setVisibility(View.VISIBLE);
homeText4x.setVisibility(View.VISIBLE);
Log.d("ShowDisclaimer", "finished showing disclaimer");
return false;
}
});
And everywhere in a background thread you wish to run your showDisclaimer(), instead you run:
showDisclaimerHandler.sendEmptyMessage(0);
I'm making an app that sends a notification to the status bar, it sends the notification when stepping through the code in the debugger, however it never sends the notification when run in realtime.
Here is my runnable that generates the notification, again when stepping through this code in the debugger the notification runs however in realtime nothing happens.
public class NewsEvents_Service extends Service {
private static final String NEWSEVENTS = "newsevents";
private static final String KEYWORDS = "keywords";
private NotificationManager mNM;
private ArrayList<NewsEvent> neList;
private int count;
#Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
neList = new ArrayList<NewsEvent>();
getKeywords();
//getNewsEvents();
Thread thr = new Thread(null, mTask, "NewsEvents_Service");
thr.start();
Log.d("Thread", "IT STARTED!!!!!!????!!!!!!!!!!!!!!!?!!?");
}
#Override
public void onDestroy() {
// Cancel the notification -- we use the same ID that we had used to start it
mNM.cancel(R.string.ECS);
// Tell the user we stopped.
Toast.makeText(this, "Service Done", Toast.LENGTH_SHORT).show();
}
/**
* The function that runs in our worker thread
*/
Runnable mTask = new Runnable() {
public void run() {
getNewsEventsFromWeb();
for(NewsEvent ne : neList){
Log.d("Thread Running", "Service Code running!!!!!!!!!!!!!!!");
String body = ne.getBody().replaceAll("\\<.*?>", "");
String title = ne.getTitle();
for(String s : keyWordList){
if(body.contains(s) || body.contains(s.toLowerCase()) ||
title.contains(s) || title.contains(s.toLowerCase())){
ne.setInterested(true);
}
}
if(ne.isInterested() == true ){
Notification note = new Notification(R.drawable.icon,
"New ECS News Event", System.currentTimeMillis());
Intent i = new Intent(NewsEvents_Service.this, FullNewsEvent.class);
i.putExtra("ne", ne);
PendingIntent pi = PendingIntent.getActivity(NewsEvents_Service.this, 0,
i, 0);
note.setLatestEventInfo(NewsEvents_Service.this, "New Event", ne.getTitle(), pi);
note.flags = Notification.FLAG_AUTO_CANCEL;
mNM.notify(R.string.ECS, note);
}
}
}
};
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Show a notification while this service is running.
*/
private void getNewsEventsFromWeb() {
HttpClient client = new DefaultHttpClient();
HttpGet get;
try {
get = new HttpGet(getString(R.string.jsonnewsevents));
ResponseHandler<String> response = new BasicResponseHandler();
String responseBody = client.execute(get, response);
String page = responseBody;
Bundle data = new Bundle();
data.putString("page",page);
Message msg = new Message();
msg.setData(data);
handler.sendMessage(msg);
}
catch (Throwable t) {
Log.d("UpdateNews", "PROBLEMS");
}
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
String page = msg.getData().getString("page");
try {
JSONArray parseArray = new JSONArray(page);
for (int i = 0; i < parseArray.length(); i++) {
JSONObject jo = parseArray.getJSONObject(i);
String title = jo.getString("title");
String body =jo.getString("body");
String pd = jo.getString("postDate");
String id = jo.getString("id");
NewsEvent ne = new NewsEvent(title, pd , body, id);
boolean unique = true;
for(NewsEvent ne0 : neList){
if(ne.getId().equals(ne0.getId())){
unique = false;
}else{
unique = true;
}
}
if(unique == true){
neList.add(ne);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
private ArrayList<String> keyWordList;
public void getNewsEvents(){
try {
InputStream fi = openFileInput(NEWSEVENTS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
neList = (ArrayList<NewsEvent>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(neList == null){
neList = new ArrayList<NewsEvent>();
}
}
public ArrayList<String> getKeywords(){
try {
InputStream fi = openFileInput(KEYWORDS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
keyWordList = (ArrayList<String>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(keyWordList == null){
keyWordList = new ArrayList<String>();
return keyWordList;
}
return keyWordList;
}
/**
* This is the object that receives interactions from clients. See RemoteService
* for a more complete example.
*/
private final IBinder mBinder = new Binder() {
#Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
return super.onTransact(code, data, reply, flags);
}
};
}
Here is my activity that schedules the service to run
public class NewsEvents extends ListActivity{
private URL JSONNewsEvents;
private ArrayList<NewsEvent> neList;
private ArrayList<String> keyWordList;
private Worker worker;
private NewsEvents ne;
public static final String KEYWORDS = "keywords";
private static final String NEWSEVENTS = "newsevents";
public static final int ONE_ID = Menu.FIRST+1;
private PendingIntent newsAlarm;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.newsevents);
ne = this;
neList = new ArrayList<NewsEvent>();
try {
JSONNewsEvents = new URL(getString(R.string.jsonnewsevents));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
worker = new Worker(handler, this);
setListAdapter(new IconicAdapter());
getKeywords();
worker.execute(JSONNewsEvents);
}
#Override
protected void onStop() {
super.onStop();
writeNewsEvents() ;
}
#Override
protected void onPause(){
super.onPause();
writeNewsEvents();
}
private void writeNewsEvents() {
try {
OutputStream fi = openFileOutput(NEWSEVENTS, 0);
if (fi!=null) {
ObjectOutputStream out = new ObjectOutputStream(fi);
out.writeObject(neList);
out.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
}
/**
* #return
*/
public ArrayList<String> getKeywords(){
try {
InputStream fi = openFileInput(KEYWORDS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
keyWordList = (ArrayList<String>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(keyWordList == null){
keyWordList = new ArrayList<String>();
return keyWordList;
}
return keyWordList;
}
public void onListItemClick(ListView parent, View v,
int position, long id) {
startFullNewsEvent(neList.get(position));
}
/**
* #param newsEvent
*/
public void startFullNewsEvent(NewsEvent ne) {
Intent intent = new Intent(this, FullNewsEvent.class);
intent.putExtra("ne", ne);
this.startActivity(intent);
finish();
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
String page = msg.getData().getString("page");
try {
JSONArray parseArray = new JSONArray(page);
for (int i = 0; i < parseArray.length(); i++) {
JSONObject jo = parseArray.getJSONObject(i);
String title = jo.getString("title");
String body =jo.getString("body");
String pd = jo.getString("postDate");
String id = jo.getString("id");
NewsEvent ne = new NewsEvent(title, pd , body, id);
boolean unique = true;
for(NewsEvent ne0 : neList){
if(ne.getId().equals(ne0.getId())){
unique = false;
}else{
unique = true;
}
}
if(unique == true){
neList.add(ne);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ne.setListAdapter(new IconicAdapter());
}
};
public class IconicAdapter extends ArrayAdapter<NewsEvent> {
IconicAdapter() {
super(NewsEvents.this, R.layout.rownews, neList);
}
public View getView(int position, View convertView,ViewGroup parent) {
LayoutInflater inflater=getLayoutInflater();
View row=inflater.inflate(R.layout.rownews, parent, false);
TextView label=(TextView)row.findViewById(R.id.label);
ImageView image= (ImageView)row.findViewById(R.id.icon);
String body = neList.get(position).getBody();
body.replaceAll("\\<.*?>", "");
String title = neList.get(position).getTitle();
for(String s : keyWordList){
if(body.contains(s) || body.contains(s.toLowerCase()) ||
title.contains(s) || title.contains(s.toLowerCase())){
neList.get(position).setInterested(true);
}
}
if(neList.get(position).isInterested() == true){
image.setImageResource(R.drawable.star);
}
label.setText(neList.get(position).getTitle());
return(row);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
populateMenu(menu);
return(super.onCreateOptionsMenu(menu));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return(applyMenuChoice(item) || super.onOptionsItemSelected(item));
}
//Creates our activity to menus
private void populateMenu(Menu menu) {
menu.add(Menu.NONE, ONE_ID, Menu.NONE, "Home");
}
private boolean applyMenuChoice(MenuItem item) {
switch (item.getItemId()) {
case ONE_ID: startHome(); return(true);
}
return(false);
}
public void startHome() {
Intent intent = new Intent(this, ECS.class);
this.startActivity(intent);
finish();
}
}
Race conditions, I'm making an HTTP Request and then handing it off to a handler, immediately following that I iterator through the array list, which at full speed is empty because the HTTP hasn't completed. In debugging it all slows down so the HTTP is complete and all works well.
Threads and Network Connections, a deadly combination.