I'm very new to android. I wanted to build client/server application, where client is running android and Server is running Java.
Clients code
package com.example.android;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.os.AsyncTask;
import java.io.*;
import java.net.*;
public class MainActivity extends Activity {
static String line= "works";
private MyTask mt;
private EditText nameField;
private TextView nameView;
private Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nameField =(EditText) findViewById(R.id.FirstInputField);
nameView =(TextView) findViewById(R.id.DisplayText);
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mt=new MyTask();
mt.execute();
}
});
}
private class MyTask extends AsyncTask<Void, String, Void>
{
protected void onPreExecute()
{
}
#Override
protected Void doInBackground(Void... params) {
Socket s;
try {
s = new Socket ("172.17.20.42", 8888);
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ios=new ObjectInputStream(s.getInputStream());
oos.writeObject(line);
oos.close();
ios.close();
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
#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;
}
}
This program works fine, but the problem is , that I'm sending static String.
doInBackground method does not have access to UI thread. The question is "How to send a strings, that are typed in UI?"
Thank you in advance
private class MyTask extends AsyncTask<Void, String, Void>
{
String line;
public MyTask(String line) {
this.line = line;
}
Then in onCreate():
public void onClick(View v) {
mt=new MyTask(nameView.getText().toString());
mt.execute();
}
Note: This is not the most efficient or memory-saving method as you instantiate a new MyTask object for each line that is sent, but is the method that demands less changes in your code as it is now.
In the on click of your button pass nameView.getText() to the MyTask, either in the constructor or the execute() method (will require you to accept the parameter as String... string and read it as string[0])
Make first generic parameter of MyTask of type String:
private class MyTask extends AsyncTask<String, String, Void>
{
protected void onPreExecute()
{
}
#Override
protected Void doInBackground(String... params) {
String stringToSend = params[0];
Socket s;
try {
s = new Socket ("172.17.20.42", 8888);
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ios=new ObjectInputStream(s.getInputStream());
oos.writeObject(stringToSend);
oos.close();
ios.close();
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
And pass the string parameter through execute:
mt.execute(new String[1] {nameField.getText().toString()});
Related
Hello I am trying to write simple client-server application in android.Here is my code for the client.
package com.sudarshan.client;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.AsyncTask;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity {
private Socket client;
private PrintWriter printwriter;
private EditText textField;
private Button button;
private String messsage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
textField = (EditText) findViewById(R.id.editText1); // reference to the text field
button = (Button) findViewById(R.id.button1); // reference to the send button
// Button press event listener
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
messsage = textField.getText().toString(); // get the text message on the text field
textField.setText(""); // Reset the text field to blank
SendMessage sendMessageTask = new SendMessage();
sendMessageTask.execute();
}
});
}
private class SendMessage extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
client = new Socket("10.0.2.2", 4444); // connect to the server
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.write(messsage); // write the message to output stream
printwriter.flush();
printwriter.close();
client.close(); // closing the connection
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
#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, menu);
return true;
}
}
Here is the code for server
package com.sudarshan.server;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class MainActivity extends AppCompatActivity {
private static ServerSocket serverSocket;
private static Socket clientSocket;
private static InputStreamReader inputStreamReader;
private static BufferedReader bufferedReader;
private static String message;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
serverSocket = new ServerSocket(4444); // Server socket
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
}
System.out.println("Server started. Listening to the port 4444");
while (true) {
try {
clientSocket = serverSocket.accept(); // accept the client connection
inputStreamReader = new InputStreamReader(clientSocket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader); // get the client message
message = bufferedReader.readLine();
System.out.println(message);
inputStreamReader.close();
clientSocket.close();
} catch (IOException ex) {
System.out.println("Problem in message reading");
}
}
}
}
The server code crashes.It gives a error as "java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sudarshan.server/com.sudarshan.server.MainActivity}: android.os.NetworkOnMainThreadException".
What am i doing wrong?
Solved.
"android.os.NetworkOnMainThreadException" means that Network related tasks are not to be done on main thread directly ie. Activity Class.So, need to make a thread under main thread then do the work.
I recover my text file distant, my text contains number one "1". I tried to convert my text "1"(char)to int, but it is giving error. I used method Integer.parseInt(String)
this is my code:
MainActivity.java
package mypackage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
PackageInfo pinfo;
String contentFichier;
TextView txt;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recoverContentTextFile();
txt = (TextView) findViewById(R.id.txt);
try {
pinfo = getPackageManager().getPackageInfo(getPackageName(), 0);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Here error
int i = Integer.parseInt(contentFichier);
}
public void recoverContentTextFile() {
new Thread() {
#Override
public void run() {
String path ="my_url_text_file";
URL u = null;
try {
u = new URL(path);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.connect();
InputStream in = c.getInputStream();
final ByteArrayOutputStream bo = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
in.read(buffer); // Read from Buffer.
bo.write(buffer); // Write Into Buffer.
runOnUiThread(new Runnable() {
#Override
public void run() {
contentFichier = bo.toString();
try {
bo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}
thank you in advance.
First of all it's not a good idea at all to use threads in the way you're implementing in your method recoverContextTextFile. What happens if the user rotate the device and the petition takes 8 minutes to complete? You have created a memory leak!
The second thing as you have created a thread the variable contentFichier will be sometimes null (because recoverContextTextFile does create a thread) and calling the Integer.parseInt(contentFichier);will raise an Exception.
For this case I think that it's better to use an AsyncTask (which I highly dislike and taking care of not leaking the activity when rotation occurs), do the petition in the onBackground method and in the method onPostExecute call the Integer.parseInt(contentFichier);.
I recommend reading this tutorial by Lars Vogel as it explains a lot about background processing.
The problem here is probably that you are trying to convert the String before the thread has finished. And also, Android has a better way than Threads to handle most (simple) background tasks, the AsyncTask. You could do something like this:
public class MainActivity extends Activity {
PackageInfo pinfo;
String contentFichier;
TextView txt;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Setup your activity here
new ContentFetcher().execute("http://......");
}
private class ContentFetcher extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
String stringResponse = null;
try{
HttpResponse httpResponse = new DefaultHttpClient().execute(new HttpGet(params[0]));
stringResponse = EntityUtils.toString(httpResponse.getEntity());
} catch (IOException ignored) {
}
return stringResponse;
}
#Override
protected void onPostExecute(String s) {
//DO something with the response here - maybe test if the s variable is indeed an integer
int i = Integer.parseInt(s);
}
}
}
To execute the task run:
new ContentFetcher().execute("http://whatever.com/mytext.txt");
Add log statement to show the value of the contentFichier:
Log.i("contentFichier", "["+contentFichier+"]"
You will see which content is being parsed. Maybe there is a whitespace on the beginning or the end. Also the server may be returning wrong value or empty string.
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import sereen.sql.Info;
import sereen.sql.InfoServicesNew;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
public class PenddingOrders extends Activity {
ArrayList<Info> info=new ArrayList<Info>();
int imgPendding=R.drawable.ex2;
ListView list;
ProgressDialog pd;
ArrayAdapter<String> adapter;
private String defValue = "N/A";
InfoServicesNew databaseHelper;
String name=InfoServicesNew.DB_TABLE_NAME;
static int img[]={R.drawable.ex2,R.drawable.ex2,R.drawable.ex2,R.drawable.ex2,
R.drawable.ex2,R.drawable.ex2,R.drawable.ex2,R.drawable.ex2, R.drawable.ex2,
R.drawable.ex2};
String data;
Intent o;
int position;
Object object;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pendding_orders);
databaseHelper = new InfoServicesNew(this);
list=(ListView)findViewById(R.id.listView1);
pd = new ProgressDialog(this);
new asy().execute("http://jsonblob.com/api/jsonBlob/53021f22e4b0f9ce1677329a");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.pendding_orders, menu);
return true;
}
public class asy extends AsyncTask<String, String, ArrayList<Info>>
{
#Override
protected ArrayList<Info> doInBackground(String... params) {
// TODO Auto-generated method stub
//activity is defined as a global variable in your AsyncTask
try {
HttpClient hc = new DefaultHttpClient();
HttpGet hg = new HttpGet(params[0]);
HttpResponse hr = hc.execute(hg);
HttpEntity he = hr.getEntity();
data = EntityUtils.toString(he);
Log.i("data", data);
}
catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
ArrayList<Info> sereenlist = new ArrayList<Info>();
sereenlist = getJSONData(data);
return sereenlist;
}
private ArrayList<Info> getJSONData(String data) {
// TODO Auto-generated method stub
ArrayList<Info> rs = null;
try {
JSONObject obj = new JSONObject(data);
JSONArray finalObj = obj.optJSONArray("orders");
for (int i = 0; i < finalObj.length(); i++)
{
final String orderNumber = finalObj.optJSONObject(i).optString(
"order-number");
final String orderAmount = finalObj.optJSONObject(i).optString(
"order-amount");
final String date = finalObj.optJSONObject(i).optString(
"date");
final String client = finalObj.optJSONObject(i).optString(
"client");
final String upperLimit = finalObj.optJSONObject(i).optString(
"upper-limit");
final String debt = finalObj.optJSONObject(i).optString(
"debt");
long id1=databaseHelper.insert(new Info(client,orderAmount,date ,orderNumber,upperLimit,debt));
// long id1 = databaseHelper.insert(info);
if(id1 < 0)
{
Toast.makeText(getApplicationContext(), "unsuccessfull add", Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(getApplicationContext(), "done", Toast.LENGTH_LONG).show();
}
// select all
}
rs = databaseHelper.selectAll();
databaseHelper.close();
Log.i("size", finalObj.length()+"");
}//try end
catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return rs;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
pd.setTitle("fetching");
pd.setMessage("waiting...");
pd.show();
}
#Override
protected void onPostExecute(ArrayList<Info> result) {
// TODO Auto-generated method stub
SetAdapterList(result);
pd.dismiss();
}
private void SetAdapterList(ArrayList<Info> result)
{
// TODO Auto-generated method stu
CustomAdapter adapter=new CustomAdapter(getApplicationContext(),result);
list.setAdapter(adapter);
//
}
}
}
strong text what i want to do is to get all the JSON data from the link .. and it show in the logcat so i get it successfully .. and then i try to insert it in the database using dbhelper and info class which contain getter and setter for all values .. but each time i run the code here what i get :
02-19 01:09:34.490: E/AndroidRuntime(1210): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
You're calling it from a worker thread. You need to call Toast.makeText() (and most other functions dealing with the UI) from within the main thread. You could use a handler, for example
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
}
});
First of all you have to get the JSON Data from network and store them in a structure.
So, the first step will be something like that . For json parsing i used Gson library. You have also to create a model class for your objects that you will receive from the requests.
private void getJSONModelHttpRequest(){
AsyncHttpClient asyncClient = new AsyncHttpClient();
asyncClient.get(YOUR_URL_HERE , new AsyncHttpResponseHandler(){
#Override
public void onStart(){
}
#Override
public void onSuccess(String response){
try {
JSONObject jsonObj = new JSONObject(response);
Gson gson = new Gson();
ModelClass model = gson.fromJson(jsonObj.toString() , ModelClass.class);
// store the models in a array list or something like that to have the data available in the future
Log.d(“Model”, " model = " +teamModel.getAnAtttributeVal);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable e,String response){
}
#Override
public void onFinish(){
// Your database insertions here
}
});
}
You can also call the Toast using handler itself, provided you use the handler's message passing feature.
What we do is pass the message which is your string using sendMessage() method inside your Thread,
handler.sendMessage(msgObj);
and tehn get the message inside the handler's handleMessage(Message msg) method using,
String aResponse = msg.getData().getString("message");
Complete example here.
in your code do it like this .first create a handler and send data to handler whatever you want to show
if(id1 < 0)
{
Message msg=new Message();
msg.obj=unsuccessfull add;
handle.sendMessage(msg);
}
Handler handle=new Handler(){
public void handleMessage(Message msg) {
String data=(String)msg.obj;
Toast.makeText(activity, data, Toast.LENGTH_SHORT).show();
}
};
i found out the problem .. it was because of the toast ... we can't make a toast inside doInBackground service .. my code worked just fine ..
How can I store all the href links I extracted using jsoup library to a String Array?
Then display it all inside a TextView?
I do not know how to use AsyncTask with String Array, nor do I know how to do a FOR LOOP during the extractions the href links from Google. I don't know what to put for the condition to make the FOR LOOP stop. My current code only returns the last href link. I hope someone can illustrate it to me. I appreciate your time!
package com.example.jsouptestarray;
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import com.example.jsouptestarray.R;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyTask().execute();
}
private class MyTask extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
Document doc;
String linkText = "";
try {
doc = Jsoup.connect("https://www.google.com/").get();
Elements links = doc.getElementsByTag("a");
for (Element el : links) {
linkText = el.attr("href");
System.out.println("Href Found!");
System.out.println("Href attribute is : "+linkText);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return linkText;
}
#Override
protected void onPostExecute(String result) {
//if you had a ui element, you could display the title
((TextView)findViewById (R.id.textView2)).append ( result );
}
}
}
Change your AsyncTask class as to return String ArrayList from doInBackground :
private class MyTask extends AsyncTask<Void, Void, ArrayList<String>> {
ArrayList<String> arr_linkText=new ArrayList<String>();
#Override
protected ArrayList<String> doInBackground(Void... params) {
Document doc;
String linkText = "";
try {
doc = Jsoup.connect("https://www.google.com/").get();
Elements links = doc.getElementsByTag("a");
for (Element el : links) {
linkText = el.attr("href");
arr_linkText.add(linkText); // add value to ArrayList
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return arr_linkText; //<< retrun ArrayList from here
}
#Override
protected void onPostExecute(ArrayList<String> result) {
// get all value from result to display in TextView
TextView textview=(TextView)findViewById(R.id.textView2);
for (String temp_result : result) {
System.out.println("links :: "+temp_result);
textview.append (temp_result +"\n");
}
}
}
sorry to be a pain, but I've been on this one too long and I am sure it's a easy one but I am tired and can't see it. All works fine but the 'String result' is empty
package com.example.me;
import java.util.ArrayList;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.widget.Button;
import android.widget.TextView;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends Activity {
Button btnLoginButton;
TextView tmpError, tmpUsername, tmpPassword;
ArrayList<NameValuePair> postParameters;
String response;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tmpError = (TextView) findViewById(R.id.lblMessage);
tmpUsername = (TextView) findViewById(R.id.txtUsername);
tmpPassword = (TextView) findViewById(R.id.txtPassword);
addListenerOnButton();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public void addListenerOnButton() {
btnLoginButton = (Button) findViewById(R.id.btnLogin);
btnLoginButton.setOnClickListener(new OnClickListener() {
public void onClick(View arg) {
try{
triggerClick();
}
catch (Exception e) {
tmpError.setText("[]" + e.toString());
}
}
});
}
private void triggerClick() {
postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("username", tmpUsername.getText().toString()));
postParameters.add(new BasicNameValuePair("password", tmpPassword.getText().toString()));
final class HttpTask
extends
AsyncTask<String/* Param */, Boolean /* Progress */, String /* Result */> {
#Override
protected String doInBackground(String... params) {
publishProgress(true);
try {
response = CustomHttpClient.executeHttpPost("http://some.url/thatiknoworks/check.php", postParameters);
return response;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected void onPostExecute(String result) {
publishProgress(false);
result = result.replaceAll("\\s+","");
if(result.equals("1")) {
tmpError.setText("Correct");
}
else {
tmpError.setText("Sorry!!("+result+")");
}
}
}
new HttpTask().execute();
}
}
come back time and time again with an empty "result" string :-(
because in the doInBackground() you return empty string, you should do:
protected String doInBackground(String... params) {
publishProgress(true);
try {
return CustomHttpClient.executeHttpPost("http://some.url/thatiknoworks/check.php", postParameters);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "";
}
}
The string result is empty because you're returning an empty string from doInBackground().
return "";
Please Declare String response; as a global variable.
protected String doInBackground(String... params)
{
publishProgress(true);
try
{
response=CustomHttpClient.executeHttpPost("http://some.url/thatiknoworks/check.php", postParameters);
return response;
}
catch (Exception e)
{
e.printStackTrace();
}
}