Parsing Objest Data Using Volley Library in Android App - android

Using this https://www.thorntech.com/2016/03/parsing-json-android-using-volley-library/ to learn how to use Volley to access and parse object data from an api get route.
When I install the apk and start the app, the screen gives me no parsed object from this api get route (single user) https://reqres.in/api/users/2
Any idea why? I've never used volley before but I read all weekend about it and it's easy to understand and implement but clearly I'm doing something wrong with pointing to the data or the response object.
I appreciate any help to point me in the right direction.
package com.volleythorntech.example;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONException;
import org.json.JSONObject;
public class MainActivity extends AppCompatActivity {
// Will show the string "data" that holds the results
TextView results;
// URL of object to be parsed
String JsonURL = "https://reqres.in/api/users/2";
// This string will hold the results
String data = "";
// Defining the Volley request queue that handles the URL request concurrently
RequestQueue requestQueue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Creates the Volley request queue
requestQueue = Volley.newRequestQueue(this);
// Casts results into the TextView found within the main layout XML with id jsonData
results = (TextView) findViewById(R.id.jsonData);
// Creating the JsonObjectRequest class called obreq, passing required parameters:
//GET is used to fetch data from the server, JsonURL is the URL to be fetched from.
JsonObjectRequest obreq = new JsonObjectRequest(Request.Method.GET, JsonURL,
// The third parameter Listener overrides the method onResponse() and passes
//JSONObject as a parameter
new Response.Listener<JSONObject>() {
// Takes the response from the JSON request
#Override
public void onResponse(JSONObject response) {
try {
JSONObject obj = response.getJSONObject("data");
// Retrieves the string labeled "colorName" and "description" from
//the response JSON Object
//and converts them into javascript objects
String color = obj.getString("first_name");
String desc = obj.getString("last_name");
// Adds strings from object to the "data" string
data += "Color Name: " + color +
"nDescription : " + desc;
// Adds the data string to the TextView "results"
results.setText(data);
}
// Try and catch are included to handle any errors due to JSON
catch (JSONException e) {
// If an error occurs, this prints the error to the log
e.printStackTrace();
}
}
},
// The final parameter overrides the method onErrorResponse() and passes VolleyError
//as a parameter
new Response.ErrorListener() {
#Override
// Handles errors that occur due to Volley
public void onErrorResponse(VolleyError error) {
Log.e("Volley", "Error");
}
}
);
// Adds the JSON object request "obreq" to the request queue
requestQueue.add(obreq);
}
}

please check permission in your manifest
<uses-permission android:name="android.permission.INTERNET"/>

Related

getResponseCode Android HttpUrlConnection [duplicate]

I have this exception and I was reading a thread on this, and it seemed confusing:
How to fix android.os.NetworkOnMainThreadException?
I already added this line to my manifest:
<uses-permission android:name="android.permission.INTERNET" />
On that discussion, they talk about the main execution thread of the app not being able to do networking. What I am wondering is how to restructure my code so that it is inline with Android good practices.
Here is my Activity class for this:
package com.problemio;
import java.io.InputStream;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class LoginActivity extends Activity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
// Show form for login_email
final EditText loginEmail = (EditText) findViewById(R.id.login_email);
String name = loginEmail.getText().toString();
// Show field for password
final EditText password = (EditText) findViewById(R.id.password);
String text = password.getText().toString();
// Show button for submit
Button submit = (Button)findViewById(R.id.submit);
// Show options for create-profile and forgot-password
submit.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
String email = loginEmail.getText().toString();
String pass = password.getText().toString();
sendFeedback(pass, email);
}
});
}
public void sendFeedback(String pass , String email)
{
Log.d( "1" , pass );
Log.d( "1" , email );
// Go to db and check if these r legit
// How do I do that? :)
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("username", email ));
postParameters.add(new BasicNameValuePair("password", pass ));
String responseString = null;
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("myUrl");
// no idea what this does :)
httppost.setEntity(new UrlEncodedFormEntity(postParameters));
// This is the line that send the request
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
}
catch (Exception e)
{
Log.e("log_tag", "Error in http connection "+e.toString());
}
}
}
What am I doing wrong here and how could I fix it? :) Thanks!!
NetworkOnMainThreadException: The exception that is thrown when an application attempts to perform a networking operation on its main thread.
You should call sendfeedback method on asynctask then only above code will work. As webserver is taking lot of time to response main thread becomes unresponsive. To avoid it you should call it on another thread. Hence asynctask is better.
here is link that illustrates how to use asynctask
NetworkOnMainThreadException is thrown when your app tries networking operation in main thread.
To fix that you can use a private inner class within your Activity that extends android.os.AsyncTask<Params, Progress, Result> which will do the server call stuffs.
Something as,
private class SendfeedbackJob extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String[] params) {
// do above Server call here
return "some message";
}
#Override
protected void onPostExecute(String message) {
//process message
}
}
And then invoke above class from submit.setOnClickListener as below,
SendfeedbackJob job = new SendfeedbackJob();
job.execute(pass, email);
References
AsyncTask doc
AsyncTask Android example
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("myUrl");
// no idea what this does :)
httppost.setEntity(new UrlEncodedFormEntity(postParameters));
// This is the line that send the request
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
}
catch (Exception e)
{
Log.e("log_tag", "Error in http connection "+e.toString());
}
Here is your problem. Since api 11, this exception will inform you that you are running long tasks on the ui thread (the http communication in your class), and according with the new StrictGuard policy this is not possibile. So you have two different choice
Use thread or aynctask in order to execut yout long term task (better way)
You made network call on main thread which is against to android rules, so you have to do your network call on separate thread like asynctask or handler etc.
You can just create Async class as below
class Retrievedata extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
try{
//Your code
}
return null;
}
}
You can just put your all code inside doInBackground method
look at this link : https://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
The exception that is thrown when an application attempts to perform a networking operation on its main thread.
Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged.
if you set minSdkVersion <11, then your application will work and you can run network operation in main thread.
After a long research (lasted half day) I have found a solution for my problem which is similar to the problem indicated here. The exception displayed by my Android Studio 2.3.3 was this:
android studio android.os.networkonmainthreadexception
The problem was based on the impossibility to set a UI variable in the MainActivity. So I saw the following video and I solved my problem. I hope it is also useful to others:
How to avoid android os NetworkOnMainThreadException
Use thread for that case,
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
//Code here
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
As indicated here, AsyncTask is deprecated, and Google recommends you use the java.util.concurrent package or Kotlin coroutines
You can execute your network task in another thread very easily using java.util.concurrent.Executors.
Simply add these two variables to your LoginActivity class:
val executor = Executors.newSingleThreadExecutor()
Then surround your networking call with an executor.execute{} block:
executor.execute {
/**
* Executes network task in background. You cannot
* access view elements here.
*/
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent()
}

How to use 'POST' Http Verb of Woocommerce REST API in JAVA/Android?

I am developing an Android app of my WooCommerce store and I'm getting store data like Products, Categories, Orders, Customers etc using GET http verb of WooCommerce REST Api. It's working fine and I'm able to generate oAuth 1.0 signature for api V2 and V3 properly. Now, I want to perform Write action. I learned from the same documentation that I need to use POST Http verb. I tried for the same and stuck.
When I'm performing any POST action with HttpGet or HttpPost request using URL, oAuth data and generated signature, I'm getting:
{"errors":[{"code":"woocommerce_api_authentication_error","message":"Invalid Signature - provided signature does not match"}]}
I'm following all the instructions given in document and found on Google as well, used "POST" string to generate oAuth signature, tried sending params using HttpGet and HttpPost but failed.
Can anyone please provide me some instruction or example to use POST Http verb for Android to perform write action using WooCommerce REST API. (like Create new Order, Create New Category etc)
I run into the same error and what I had to do was to create a different POST adapter class. I am using retrofit for network calls and here is my snippet code:
package me.gilo.a55thavenue.data;
import android.util.Base64;
import android.util.Log;
import com.squareup.okhttp.HttpUrl;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import retrofit.GsonConverterFactory;
import retrofit.Retrofit;
import retrofit.RxJavaCallAdapterFactory;
/**
* Created by Aron on 10/31/2015.
*/
public class PostRestAdapter {
static String oauth_nonce = "";
static String oauth_timestamp = "";
static String oauth_signature_method = "HMAC-SHA1";
static ArrayList<NameValuePair> params;
public static API createAPI(final String endpoint) {
setParams(endpoint);
// Define the interceptor, add authentication headers
Interceptor interceptor = new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
HttpUrl.Builder builder = chain.request().httpUrl().newBuilder();
for (NameValuePair entry : params) {
builder.addQueryParameter(entry.getName(), entry.getValue());
}
Request newRequest = chain.request()
.newBuilder()
.url(builder.build())
.build();
return chain.proceed(newRequest);
}
};
// Add the interceptor to OkHttpClient
OkHttpClient client = new OkHttpClient();
client.interceptors().add(interceptor);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API.BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit.create(API.class);
}
public static ArrayList<NameValuePair> setParams(String endpoint) {
final String uri = API.BASE_URL + endpoint;
oauth_nonce = getOauth_nonce();
oauth_timestamp = getOauth_timestamp();
params = new ArrayList<>();
params.add(new BasicNameValuePair("oauth_consumer_key", API.CONSUMER_KEY));
params.add(new BasicNameValuePair("oauth_nonce", oauth_nonce));
params.add(new BasicNameValuePair("oauth_timestamp", oauth_timestamp));
params.add(new BasicNameValuePair("oauth_signature_method", oauth_signature_method));
Collections.sort(params, new SortParams());
String encodedParams = URLEncodedUtils.format(params, "utf-8");
Log.d("encodedParamString", encodedParams);
String string_to_sign = "";
try {
string_to_sign = (new StringBuilder("POST&")).append(URLEncoder.encode(uri, "utf-8")).append("&").append(URLEncoder.encode(encodedParams, "utf-8")).toString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Log.d("string to sign", string_to_sign);
try {
Mac mac = Mac.getInstance("HMAC-SHA1");
String secret = API.CONSUMER_SECRET;
if (API.WP_API_VERSION.equals("3")) {
secret = API.CONSUMER_SECRET + "&";
}
mac.init(new SecretKeySpec(secret.getBytes("utf-8"), "HMAC-SHA1"));
String signature = Base64.encodeToString(mac.doFinal(string_to_sign.getBytes("utf-8")), 0).trim();
Log.d("signature", signature);
params.add(new BasicNameValuePair("oauth_signature", signature));
} catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
e.printStackTrace();
}
return params;
}
public static String getOauth_nonce() {
return (new StringBuilder(String.valueOf(Math.random() * 100000000D))).toString();
}
public static String getOauth_timestamp() {
long stamp = (long) (System.currentTimeMillis() / 1000D);
Log.d("stamp", stamp + "");
return (new StringBuilder(String.valueOf(stamp))).toString();
}
static class SortParams implements Comparator<NameValuePair> {
#Override
public int compare(NameValuePair nameValuePair1, NameValuePair nameValuePair2) {
return nameValuePair1.getName().compareTo(nameValuePair2.getName());
}
}
}
[Source: https://gist.github.com/Aroniez/41dbc5942f70641b397e]

How to request movie data from Rotten Tomatoes using their JSON API?

In my Android application I have one EditText, one Button, and one Listview. When I type a movie name into my EditText field and press on the Button, I want the ListView to be populated with movie names from the Rotten Tomatoes website that match what I entered into the EditText field.
But I can't figure out how to use the Rotten Tomatoes JSON API to get the movie data. How do I do it?
Basically, you need to do four things:
Get a Rotten Tomatoes API key for your Android application, which you can do here. This key identifies your app to their service and gives you authorized access. You must use it every time you make a request to their API. That's all, nothing complicated.
Make a HTTP request to their API's web server. The URL of the request will depend on what data you're trying to fetch. For example, to get a list of movies the URL is: http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=[your_api_key]&q=[search_keyword]&page_limit=[page_limit], as shown on this page.
Read the response from their web server. As shown on the last page I just linked, the response will be a JSON object, because that's the data format Rotten Tomatoes' chose to use for their API.
Get whatever values from the JSON object that you want (e.g. movie title) and update your app's UI accordingly.
I've put together a small demo app that will do this. Please try out the code below.
MainActivity.java
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class MainActivity extends Activity
{
// the Rotten Tomatoes API key of your application! get this from their website
private static final String API_KEY = <your api key!>;
// the number of movies you want to get in a single request to their web server
private static final int MOVIE_PAGE_LIMIT = 10;
private EditText searchBox;
private Button searchButton;
private ListView moviesList;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
searchBox = (EditText) findViewById(R.id.text_search_box);
searchButton = (Button) findViewById(R.id.button_search);
searchButton.setOnClickListener(new OnClickListener()
{
// send an API request when the button is pressed
#Override
public void onClick(View arg0)
{
new RequestTask().execute("http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=" + API_KEY + "&q=" + searchBox.getText().toString().trim() + "&page_limit=" + MOVIE_PAGE_LIMIT);
}
});
moviesList = (ListView) findViewById(R.id.list_movies);
}
private void refreshMoviesList(String[] movieTitles)
{
moviesList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, movieTitles));
}
private class RequestTask extends AsyncTask<String, String, String>
{
// make a request to the specified url
#Override
protected String doInBackground(String... uri)
{
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
String responseString = null;
try
{
// make a HTTP request
response = httpclient.execute(new HttpGet(uri[0]));
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK)
{
// request successful - read the response and close the connection
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
}
else
{
// request failed - close the connection
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
}
catch (Exception e)
{
Log.d("Test", "Couldn't make a successful request!");
}
return responseString;
}
// if the request above completed successfully, this method will
// automatically run so you can do something with the response
#Override
protected void onPostExecute(String response)
{
super.onPostExecute(response);
if (response != null)
{
try
{
// convert the String response to a JSON object,
// because JSON is the response format Rotten Tomatoes uses
JSONObject jsonResponse = new JSONObject(response);
// fetch the array of movies in the response
JSONArray movies = jsonResponse.getJSONArray("movies");
// add each movie's title to an array
String[] movieTitles = new String[movies.length()];
for (int i = 0; i < movies.length(); i++)
{
JSONObject movie = movies.getJSONObject(i);
movieTitles[i] = movie.getString("title");
}
// update the UI
refreshMoviesList(movieTitles);
}
catch (JSONException e)
{
Log.d("Test", "Failed to parse the JSON response!");
}
}
}
}
}
res/layouts/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#E9E9E9"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="horizontal"
android:padding="3dip" >
<EditText
android:id="#+id/text_search_box"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center" />
<Button
android:id="#+id/button_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableRight="#android:drawable/ic_search_category_default" />
</LinearLayout>
<ListView
android:id="#+id/list_movies"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1.0" />
</LinearLayout>
And add this line to your AndroidManifest.xml (it gives your Android app permission to use the Internet, which you obviously need to make the request to Rotten Tomatoes' web server):
<uses-permission android:name="android.permission.INTERNET" />
Bonus answer:
If you want "live" search results as you type the search keyword into the EditText field, add a TextWatcher via EditText's addTextChangedListener() method, and make it do the HTTP request in onTextChanged().
A typical approach to this kind of problem would be:
Create an AsyncTask that handles the networking and parsing of your request and the response, since long running operations in the main (or UI) thread is a bad idea. In the AsyncTask you communicate to the API server using a HttpClient and parse the JSON request/response using a JSON parser library, such as Google's gson.
You can find plenty of tutorials on how to communicate with remote servers using the HttpClient, here is one of them (I can't vouch for it's quality):
http://www.mysamplecode.com/2011/09/android-asynctask-httpclient-with.html

GSON: Expected a string but was BEGIN_OBJECT?

I'm trying to use GSON to parse some very simple JSON. Here's my code:
Gson gson = new Gson();
InputStreamReader reader = new InputStreamReader(getJsonData(url));
String key = gson.fromJson(reader, String.class);
Here's the JSON returned from the url:
{
"access_token": "abcdefgh"
}
I'm getting this exception:
E/AndroidRuntime(19447): com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2
Any ideas? I'm new to GSON.
The JSON structure is an object with one element named "access_token" -- it's not just a simple string. It could be deserialized to a matching Java data structure, such as a Map, as follows.
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class GsonFoo
{
public static void main(String[] args)
{
String jsonInput = "{\"access_token\": \"abcdefgh\"}";
Map<String, String> map = new Gson().fromJson(jsonInput, new TypeToken<Map<String, String>>() {}.getType());
String key = map.get("access_token");
System.out.println(key);
}
}
Another common approach is to use a more specific Java data structure that matches the JSON. For example:
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
public class GsonFoo
{
public static void main(String[] args)
{
String jsonInput = "{\"access_token\": \"abcdefgh\"}";
Response response = new Gson().fromJson(jsonInput, Response.class);
System.out.println(response.key);
}
}
class Response
{
#SerializedName("access_token")
String key;
}
Another "low level" possibility using the Gson JsonParser:
package stackoverflow.questions.q11571412;
import com.google.gson.*;
public class GsonFooWithParser
{
public static void main(String[] args)
{
String jsonInput = "{\"access_token\": \"abcdefgh\"}";
JsonElement je = new JsonParser().parse(jsonInput);
String value = je.getAsJsonObject().get("access_token").getAsString();
System.out.println(value);
}
}
If one day you'll write a custom deserializer, JsonElement will be your best friend.
This is normal parsing exception occurred when Pojo key data type is different from json response
This is due to data type mismatch in Pojo class and actually data which comes in the Network api Response
Eg
data class ProcessResponse(
val outputParameters: String,
val pId: Int
)
got the same error due to api gives response as
{
"pId": 1",
"outputParameters": {
"": ""
}
}
Here POJO is outputParameters is String but as per api response its json

Android - android.os.NetworkOnMainThreadException

I have this exception and I was reading a thread on this, and it seemed confusing:
How to fix android.os.NetworkOnMainThreadException?
I already added this line to my manifest:
<uses-permission android:name="android.permission.INTERNET" />
On that discussion, they talk about the main execution thread of the app not being able to do networking. What I am wondering is how to restructure my code so that it is inline with Android good practices.
Here is my Activity class for this:
package com.problemio;
import java.io.InputStream;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class LoginActivity extends Activity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
// Show form for login_email
final EditText loginEmail = (EditText) findViewById(R.id.login_email);
String name = loginEmail.getText().toString();
// Show field for password
final EditText password = (EditText) findViewById(R.id.password);
String text = password.getText().toString();
// Show button for submit
Button submit = (Button)findViewById(R.id.submit);
// Show options for create-profile and forgot-password
submit.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
String email = loginEmail.getText().toString();
String pass = password.getText().toString();
sendFeedback(pass, email);
}
});
}
public void sendFeedback(String pass , String email)
{
Log.d( "1" , pass );
Log.d( "1" , email );
// Go to db and check if these r legit
// How do I do that? :)
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("username", email ));
postParameters.add(new BasicNameValuePair("password", pass ));
String responseString = null;
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("myUrl");
// no idea what this does :)
httppost.setEntity(new UrlEncodedFormEntity(postParameters));
// This is the line that send the request
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
}
catch (Exception e)
{
Log.e("log_tag", "Error in http connection "+e.toString());
}
}
}
What am I doing wrong here and how could I fix it? :) Thanks!!
NetworkOnMainThreadException: The exception that is thrown when an application attempts to perform a networking operation on its main thread.
You should call sendfeedback method on asynctask then only above code will work. As webserver is taking lot of time to response main thread becomes unresponsive. To avoid it you should call it on another thread. Hence asynctask is better.
here is link that illustrates how to use asynctask
NetworkOnMainThreadException is thrown when your app tries networking operation in main thread.
To fix that you can use a private inner class within your Activity that extends android.os.AsyncTask<Params, Progress, Result> which will do the server call stuffs.
Something as,
private class SendfeedbackJob extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String[] params) {
// do above Server call here
return "some message";
}
#Override
protected void onPostExecute(String message) {
//process message
}
}
And then invoke above class from submit.setOnClickListener as below,
SendfeedbackJob job = new SendfeedbackJob();
job.execute(pass, email);
References
AsyncTask doc
AsyncTask Android example
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("myUrl");
// no idea what this does :)
httppost.setEntity(new UrlEncodedFormEntity(postParameters));
// This is the line that send the request
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
}
catch (Exception e)
{
Log.e("log_tag", "Error in http connection "+e.toString());
}
Here is your problem. Since api 11, this exception will inform you that you are running long tasks on the ui thread (the http communication in your class), and according with the new StrictGuard policy this is not possibile. So you have two different choice
Use thread or aynctask in order to execut yout long term task (better way)
You made network call on main thread which is against to android rules, so you have to do your network call on separate thread like asynctask or handler etc.
You can just create Async class as below
class Retrievedata extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
try{
//Your code
}
return null;
}
}
You can just put your all code inside doInBackground method
look at this link : https://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
The exception that is thrown when an application attempts to perform a networking operation on its main thread.
Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged.
if you set minSdkVersion <11, then your application will work and you can run network operation in main thread.
After a long research (lasted half day) I have found a solution for my problem which is similar to the problem indicated here. The exception displayed by my Android Studio 2.3.3 was this:
android studio android.os.networkonmainthreadexception
The problem was based on the impossibility to set a UI variable in the MainActivity. So I saw the following video and I solved my problem. I hope it is also useful to others:
How to avoid android os NetworkOnMainThreadException
Use thread for that case,
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
//Code here
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
As indicated here, AsyncTask is deprecated, and Google recommends you use the java.util.concurrent package or Kotlin coroutines
You can execute your network task in another thread very easily using java.util.concurrent.Executors.
Simply add these two variables to your LoginActivity class:
val executor = Executors.newSingleThreadExecutor()
Then surround your networking call with an executor.execute{} block:
executor.execute {
/**
* Executes network task in background. You cannot
* access view elements here.
*/
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent()
}

Categories

Resources