I am currently trying to make an android app that basically downloads strings from a url. But I want to make it object oriented. My mainActivity gets string from webService which downloads string when button is clicked. But I am not good at interfaces and callbacks. What should I do to make this code run?
public class MainActivity extends Activity implements WebServiceInterface{
private TextView textView;
private Button readWebPage;
private WebService service;
private WebServiceInterface webServiceInterface;
private String response;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.TextView01);
readWebPage = (Button) findViewById(R.id.readWebpage);
service = new WebService();
readWebPage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
service.execute(new String[]{"http://google.com/"});
onSuccess(response);
}
});
}
#Override
public void onSuccess(String response) {
textView.setText(Html.fromHtml(response));
}
#Override
public void onFail(Exception ex) {
textView.setText(ex.getLocalizedMessage());
}
}
public class WebService extends AsyncTask<String, Void, String> {
private WebServiceInterface webServiceInterface;
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
webServiceInterface.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
webServiceInterface.onFail(e);
}
}
return response;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
public interface WebServiceInterface {
void onSuccess(String response);
void onFail(Exception ex);
}
you need to create one public method for set webServiceInterface in WebService class like
public setWebServiceInterface (WebServiceInterface listener)
{
this.webServiceInterface =listener;
}
in MainActivity activity call this method and pass argument this
service.setWebServiceInterface (this);
in WebService class in onPostExecute Method call
webServiceInterface.onSuccess(s);
Add WebService (WebServiceInterface webServiceInterface) in your AsyncTask as a constructor.
service = new WebService(new WebServiceInterface (){
void onSuccess(String response){
//do your stuff
}
void onFail(Exception ex){
//do your stuff
}
});
and in your asynctask
public class WebService extends AsyncTask<String, Void, String> {
public WebService (WebServiceInterface webServiceInterface){
this.webinterface= webServiceInterface;
}
private WebServiceInterface webinterface;
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
webinterface.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
webinterface.onFail(e);
}
}
return response;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
I have found the problem, it is because of runOnUiThread is missing.
Related
I am trying to make a GET request on a URL, I created a class extending AsyncTask<Void, Void, Void> and I try to call new MyClass.execute() ... I have done this before and it worked, today it is not working. What am I doing wrong?
Here is my code:
public class SignUpActivity extends AppCompatActivity {
String TAG = SignUpActivity.class.getSimpleName();
String URL;
ArrayList<String> countries = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up);
new MyClass.execute();
}
private class MyClass extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
//TODO
}
#Override
protected Void doInBackground(Void... params) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(URL, "GET");
//Handling response in jsonStr code
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//TODO
}
}
This is a syntax error. It should be
new MyClass().execute();
not as new MyClass.execute();
use this to get data use return to return value:
public class SignUpActivity extends AppCompatActivity {
String TAG = SignUpActivity.class.getSimpleName();
String URL;
ArrayList<String> countries = new ArrayList<>();
String jsonStr="";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up);
String response = new MyClass.execute();
}
private class MyClass extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
//TODP
}
#Override
protected String doInBackground(Void... params) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(URL, "GET");
//Handling response in jsonStr code
return jsonStr;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//TODO
jsonStr = result;
}
}
}
public class JsonHandler {
static String response = null;
public final static int GET = 1;
public final static int POST = 2;
public JsonHandler() {
}
public String makeServiceCall(String url,int method) {
return this.makeServiceCall(url, method, null);
}
public String makeServiceCall(String url, int method,
List<NameValuePair> params) {
try {
// http client
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
// Checking http request method type
if (method == POST) {
HttpPost httpPost = new HttpPost(url);
if (params != null) {
httpPost.setEntity(new UrlEncodedFormEntity(params));
}
httpResponse = httpClient.execute(httpPost);
} else if (method == GET) {
if (params != null) {
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
}
HttpGet httpGet = new HttpGet(url);
httpResponse = httpClient.execute(httpGet);
}
httpEntity = httpResponse.getEntity();
response = EntityUtils.toString(httpEntity);
} catch (Exception e) {
}
return response;
}
}
Add above class to your main package and do it as doInBackground
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
JsonHandler json = new JsonHandler();
String jsonStr = json.makeServiceCall(params[0], JsonHandler.GET);
// parse your json data here
}
I have declared a private field in the MainActivity Class with getter and setter method. Now I want to setText from another class in this field. But after running the device the app is crushing. I want to fetch some json data by using this code. I am not getting how to call this field from another class and how to set the value to run the app smoothly. My code looks like this.
public class MainActivity extends AppCompatActivity {
private TextView tvData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnHit=(Button)findViewById(R.id.btnHit);
tvData=(TextView)findViewById(R.id.tvJsonItem);
btnHit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
JSONTask jsonTask=new JSONTask("https://jsonparsingdemo-cec5b.firebaseapp.com/jsonData/moviesDemoItem.txt"); //error showing this cannot be applied
jsonTask.execute();
}
});
}
The another class is
public class JSONTask extends AsyncTask<String,String,String>{
private TextView tvData;
public JSONTask(TextView tvData) {
this.tvData =tvData;
}
#Override
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
return buffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
tvData.setText(result);
}
}
Make your AsyncTask like this:
class JSONTask extends AsyncTask<String ,String,String>{
private TextView textView;
public JSONTask(TextView textView) {
this.textView = textView;
}
#Override
protected String doInBackground(String... params) {
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
textView.setText(s);
}
}
now call this class from MainActivity
JSONTask jsonTask = new JSONTask(yourTextView);
jsonTask.execute();
Hope it will work for you .
#override
protected void onPostExecute(String result){
super.onPostExecute(result);
new MainActivity().setTvData().setText(result);
Use setTvData().setText() to set the value if you only one data in your json string .
I am trying to send a POST request to a php file and when the user is asked for login information, if wrong, it prints the json message from the php file and if right, it allows user to login. However, my application crashes, giving a NetworkOnThreadMainException pointing errors to three lines.
HttpResponse response=httpClient.execute(httpPost);
public class LoginActivity extends ActionBarActivity {
login();
So how can i make this possible?
This is some part of the code I have written:
public class LoginActivity extends ActionBarActivity {
EditText et, et2;
ImageButton ib5;
String name,pwd;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
et = (EditText) findViewById(R.id.editText);
et2 = (EditText) findViewById(R.id.editText2);
ib5 = (ImageButton) findViewById(R.id.imageButton5);
name=et.getText().toString();
pwd=et2.getText().toString();
final LoginActivity loginActivity=null;
ib5.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//login();
new DownloadFilesTask(loginActivity,name,pwd).doInBackground();
}
});
}
public void login() {
new LoginTask(this, et.getText().toString(), et2.getText().toString());
}
private class LoginTask {
public LoginTask(LoginActivity loginActivity, String name, String pwd) {
}
}
void navigatetoMainActivity() {
Intent homeIntent = new Intent(getApplicationContext(), MainActivity.class);
homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(homeIntent);
}
void InvalidToast(){
Toast.makeText(getApplicationContext(), "Please enter valid name and password", Toast.LENGTH_LONG).show();
}
void EmptyToast(){
Toast.makeText(getApplicationContext(), "Please fill the form, don't leave any field blank", Toast.LENGTH_LONG).show();
}
}
DownloadFilesTask.java
public class DownloadFilesTask extends AsyncTask<String, String, String> {
private String name, pwd;
private LoginActivity loginActivity;
public DownloadFilesTask(LoginActivity loginActivity,String name, String pwd){
this.loginActivity=loginActivity;
this.name=name;
this.pwd=pwd;
}
#Override
protected String doInBackground(String... strings) {
HttpClient httpClient=new DefaultHttpClient();
HttpPost httpPost=new HttpPost("login.php");
List<NameValuePair> nameValuePairs=new ArrayList<NameValuePair>(2);
String result=null;
nameValuePairs.add(new BasicNameValuePair("name", name));
nameValuePairs.add(new BasicNameValuePair("password", pwd));
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
HttpResponse response= null;
try {
response = httpClient.execute(httpPost); //error is given here
} catch (IOException e) {
e.printStackTrace();
}
HttpEntity entity=response.getEntity();
InputStream instream= null;
try {
instream = entity.getContent();
} catch (IOException e) {
e.printStackTrace();
}
result=convertStreamToString(instream);
try {
instream.close();
} catch (IOException e) {
e.printStackTrace();
}
if (Utility.isNotNull(name) && Utility.isNotNull(pwd)) {
RequestParams params = new RequestParams();
if (Utility.validate(name, pwd)) {
params.put("username", name);
params.put("password", pwd);
onPostExecute();
} else {
loginActivity.InvalidToast();
}
} else {
loginActivity.EmptyToast();
}
return result;
}
private String convertStreamToString(InputStream instream) {
BufferedReader reader=new BufferedReader(new InputStreamReader(instream));
StringBuilder sb=new StringBuilder();
String line=null;
try {
while ((line=reader.readLine())!=null){
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
instream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
protected void onPostExecute(){
loginActivity.navigatetoMainActivity();
}
private static class Utility {
static Pattern pattern;
static Matcher matcher;
static Pattern pattern1;
static Matcher matcher1;
static String NAME_PATTERN="SuperBoise";
static String PWD_PATTERN="qwerty";
public static boolean validate(String name,String pwd){
pattern=Pattern.compile(NAME_PATTERN);
pattern1=Pattern.compile(PWD_PATTERN);
matcher=pattern.matcher(name);
matcher1=pattern1.matcher(pwd);
return matcher.matches()&& matcher1.matches();
}
public static boolean isNotNull(String name) {
return name!=null && name.trim().length()>0 ? true: false;
}
}
}
Your application has 1 main thread running all the time when it is not paused which is called the UI Thread.
As of the latest versions of Android, you are not permitted to make any network related actions on the UI Thread because it is time-consuming and it blocks the main thread which is responsible for drawing all the UI and registering the clicks, etc. (there is a way to bypass this but it is HIGHLY NOT RECOMMENDED)
An easy way to perform network related actions such as logging in, is the AsyncTask class implemented by Android.
The class runs on a very simple principle, it has 2 methods which run on the UI Thread: the onPreExecute() and the onPostExecute() methods.
And it has a method that runs on a Background Thread which is called the doInBackground() (this is where you should do all your network related actions
Here is a very basic example of an AsyncTask class:
public class DownloadFilesTask extends AsyncTask<void, void, void> {
public DownloadFilesTask(){
// Here you can pass data to the task
// if you want to pass more than 1 type of data
}
protected void onPreExecute(){
// this is executed on the UI Thread
// so you can modify elements inside the UI Thread
// this is called after execute() is called and
// before doInBackground() is called
}
protected void doInBackground(Void... params) {
//here you do all your network related stuff
return null;
}
protected void onPostExecute(Void result) {
// here you can work on the UI Thread
// this is executed after the AsyncTask's execute() is finished
// (after doInBackground() is done)
}
}
And to use this task you can just simply call it from the UI Thread like this:
new DownloadFilesTask().execute();
This is the AsyncTask documentation page on the developer.android.com: AsyncTask
You could pass a reference to your LoginActivity through the constructor of the task and if the login is valid then you can call the navigatetoMainActivity() method from your onPostExecute() inside the task
Edit1: How your LoginActivity should look:
public class LoginActivity extends ActionBarActivity {
EditText et, et2;
ImageButton ib5;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
et = (EditText) findViewById(R.id.editText);
et2 = (EditText) findViewById(R.id.editText2);
ib5 = (ImageButton) findViewById(R.id.imageButton5);
ib5.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
login();
}
});
}
public void login(){
new LoginTask(this, et.getText().toString(), et2.getText.toString()).execute();
}
}
Edit2: This is how your task should look like:
public class LoginTask extends AsyncTask<void , void, void> {
private String user, password;
private LoginActivity loginActivity;
public LoginTask(LoginActivity loginActivity, String user, String password){
this.loginActivity = loginActivity;
this.user = user;
this.password = password;
}
#Override
protected String doInBackground(Void... params) {
//do all the networking here
}
protected void onPostExecute(Void results){
super.onPostExecute(results);
loginActivity.navigatetoMainActivity();
}
}
I am working on a chat application. Currently i did like that when i open the ChatActvity, all sockets are registered and the chatting works... Now i want to change the coding structure.. I want to open the sockets in a class, not in Activity class and i need to add a listener to that class. How i implement this..?
private class Chatroom {
private static void initialise() {
// Initialising the sockets and registering listeners to each socket
}
}
I want to notify in my activity class when the socket listeners in the Chatroom class get called..
here is probably what you need :
public class RequestSender extends AsyncTask<String, Void, String> {
private final static String serverIP = "192.168.1.1";
private final static Integer serverPort = 1234;
private ServerResponseListener listener = null;
public void setServerResponseListener(ServerResponseListener listener){
this.listener=listener;
}
public interface ServerResponseListener {
public void onResponseReceive(String response);
}
#Override
protected String doInBackground(String... params) {
Socket socket = null;
try {
socket = new Socket(serverIP, serverPort);
} catch (IOException e) {
// return "server is unreachable" message or something
}
PrintWriter requestWriter = new PrintWriter(socket.getOutputStream());
BufferedReader resultReader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
String request = params[0] //for example
requestWriter.println(request);
requestWriter.flush();
String result = null;
while ((result = resultReader.readLine()) != null) {}
return result;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
listener.onResponseReceive(result);
}
}
here is example how to execute AsynchTask from Activity :
public class MainActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RequestSender requestSender = new RequestSender();
requestSender.setServerResponseListener(new RequestSender.ServerResponseListener(){
#override
public void onResponseReceive(String response){
//
}
});
requestSender.execute("message");
}
}
read this : http://developer.android.com/reference/android/os/AsyncTask.html
I'm trying to make a simple webreader work in an AsyncTast,
main thread
public class main extends Activity implements CallBackListener{
...
WebReader wr = new WebReader();
wr.execute("http://www.google.com");
...
#Override
public void callback(String res)
{
Log.e("eee",res);
}
...
}
...
interface CallBackListener
{
void callback(String res);
}
and webreader
class WebReader extends AsyncTask<String, Void, String>{
CallBackListener mListener;
public void setListener(CallBackListener listener){
mListener = listener;
}
#Override
protected String doInBackground(String... urls) {
String response = "";
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(urls[0]);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
#Override
protected void onPostExecute(String result) {
Log.e("s3","ss"+result);
mListener.callback(result); // null point here
}
}
yet it crashed with a nullpoint at mListener.callback ... any ideas what might be wrong?
Thanks!
You are not setting a listener. You should have something like this:
WebReader wr = new WebReader();
wr.setListener( new YourCallbackListener() );
wr.execute("http://www.google.com");