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

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

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()
}

Parsing Objest Data Using Volley Library in Android App

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"/>

Error with using HttpPost on Android

I am trying to input text from Android into websites, and I read that httppost is a good option. I download the HttpClient 4.2.2 (GA) tar.gz, unzipped them, and copied the 7 jars into the lib folder of my android project in Eclipse. I'm pretty sure I got all the jars, since they matched those listed on the website.
I then proceeded to copy and paste the top tutorial from: http://hc.apache.org/httpcomponents-client-ga/quickstart.html
I imported everything, and was left with this error:
EntityUtils.consume(entity1); //X
} finally {
httpGet.releaseConnection(); //X
This portion of code is at two places in the tutorial, and errors occur at both.
Eclipse says for the first line:
"The method consume(HttpEntity) is undefined for the type EntityUtils."
Second line:
"The method releaseConnection() is undefined for the type HttpGet."
I'm pretty sure I downloaded every jar, transported them correctly, and imported everything. What is making the error? Thanks.
Here is what I have now. Edward, I used some of the code from your methods, but just put them into onCreate. However, this isn't working. A few seconds after I go from the previous activity to this one, I get the message that the app "has stopped unexpectedly".
I have a question about inputting my Strings into the website text fields: Do I use NameValuePairs of HttpParams? Here's my code, can you see what's wrong? Thanks.
package com.example.myapp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;
public class BalanceCheckerActivity extends Activity {
private final String LOGIN_URL = "https://someloginsite.com"; //username and password
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_balance_checker);
String username = getIntent().getExtras().getString("username");
String password = getIntent().getExtras().getString("password");
//Building post parameters, key and value pair
List<NameValuePair> accountInfo = new ArrayList<NameValuePair>(2);
accountInfo.add(new BasicNameValuePair("inputEnterpriseId", username));
accountInfo.add(new BasicNameValuePair("password", password));
//Creating HTTP client
HttpClient httpClient = new DefaultHttpClient();
//Creating HTTP Post
HttpPost httpPost = new HttpPost(LOGIN_URL);
BasicHttpParams params = new BasicHttpParams();
params.setParameter("inputEnterpriseID", username);
params.setParameter("password", password);
httpPost.setParams(params);
//Url Encoding the POST parameters
try {
httpPost.setEntity(new UrlEncodedFormEntity(accountInfo));
}
catch (UnsupportedEncodingException e) {
// writing error to Log
e.printStackTrace();
startActivity(new Intent(this, AccountInputActivity.class));
}
HttpResponse response = null;
InputStreamReader iSR = null;
String source = null;
// Making HTTP Request
try {
response = httpClient.execute(httpPost);
// writing response to log
Log.d("Http Response:", response.toString());
iSR = new InputStreamReader(response.getEntity().getContent());
BufferedReader br = new BufferedReader(iSR);
source = "";
while((source = br.readLine()) != null)
{
source += br.readLine();
}
} catch (ClientProtocolException e) {
// writing exception to log
e.printStackTrace();
startActivity(new Intent(this, AccountInputActivity.class));
} catch (IOException e) {
// writing exception to log
e.printStackTrace();
startActivity(new Intent(this, AccountInputActivity.class));
}
System.out.println(source);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_balance_checker, menu);
return true;
}
}
That mostly looks pretty good to me. I only saw one obviously wrong piece of code in it:
while((source = br.readLine()) != null)
{
source += br.readLine();
}
That's kind of a mess, and rather than try to untangle it, I'll just rewrite it.
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null)
sb.append(line);
String source = sb.toString();
Also, you shouldn't be doing network I/O from onCreate() or even from within your UI thread, since it can block for a long time, freezing your entire UI and possibly causing an "Application Not Responding" (ANR) crash. But for a simple test program, you can let that slide for now. For production code, you'd launch a thread or use AsyncTask().
Anyway, we're not really interested in building and debugging your program for you. Have you tried this code out? What was the result?
One final note: a login sequence like this is likely to return an authentication token in the form of a cookie. I forget how you extract cookies from an HttpResponse, but you'll want to do that, and then include any received cookies as part of any subsequent requests to that web site.
Original answer:
I think you've gotten yourself all tangled up. The Apache http client package is built into Android, so there's no need to download any jar files from apache.
I'm not familiar with EntityUtils, but whatever it is, if you can avoid using it, I would do so. Try to stick with the bundled API whenever possible; every third-party or utility library you add to your application increases bloat, and on mobile devices, you want to keep your application as light as possible. As for the actual "consume()" method not being found, that's probably a mistake in the documentation. They probably meant consumeContent().
The releaseConnection() call is probably only necessary for persistent connection. That's relatively advanced usage; I don't even do persistent or managed connections in my own code.
You haven't provided enough information to let us know what it is you're trying to do, but I'll try give you a reasonably generic answer.
There are many, many ways to transmit data to a server over the http protocol, but in the vast majority of cases you want to transmit form-encoded data via HttpPost.
The procedure is:
Create a DefaultHttpClient
Create an HttpPost request
Add headers as needed with setHeader() or addHeader().
Add the data to be transmitted in the form of an HttpEntity
Call client.execute() with the post request
Wait for and receive an HttpResponse; examine it for status code.
If you're expecting data back from the server, use response.getEntity()
There are many HttpEntity classes, which collect their data and transmit it to the server each in their own way. Assuming you're transmitting form-encoded data, then UrlEncodedFormEntity is the one you want. This entity takes a list of NameValuePair objects which it formats properly for form-encoded data and transmits it.
Here is some code I've written to do this; these are only code fragments so I'll leave it to you to incorporate them into your application and debug them yourself.
/**
* POST the given url, providing the given list of NameValuePairs
* #param url destination url
* #param data data, as a list of name/value pairs
*/
public HttpResponse post(String url, List<NameValuePair> data) {
HttpPost req = new HttpPost(url);
UrlEncodedFormEntity e;
try {
e = new UrlEncodedFormEntity(data, "UTF-8");
} catch (UnsupportedEncodingException e1) {
Log.e(TAG, "Unknown exception: " + e1);
return null; // Or throw an exception, it's up to you
}
return post(req, e);
}
/**
* Post an arbitrary entity.
* #param req HttpPost
* #param data Any HttpEntity subclass
* #return HttpResponse from server
*/
public HttpResponse post(HttpPost req, HttpEntity data) {
try {
HttpClient client = new DefaultHttpClient();
req.setEntity(data);
HttpResponse resp = client.execute(req);
int status = resp.getStatusLine().getStatusCode();
if (status != HttpStatus.SC_OK) {
Log.w(TAG,
"http error: " + resp.getStatusLine().getReasonPhrase());
return null; // Or throw an exception, it's up to you
}
return resp;
} catch (ClientProtocolException e) {
Log.e(TAG, "Protocol exception: " + e);
return null;
} catch (UnknownHostException e) {
return null;
} catch (IOException e) {
Log.e(TAG, "IO exception: " + e);
return null;
} catch (Exception e) {
// Catch-all
Log.e(TAG, "Unknown exception: " + e);
return null;
}
}

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()
}

How to transfer SQLite db to web server on android phone (android)

I have "BackUpContacts.db" database in SQLiteDatabase, it has a table named "ContactInfo" with column names ContactId, ContactName, MobilePhone1, MobilePhone2, OfficePhone1, OfficePhone2, OfficePhone3, HomePhone1, HomePhone2 and TokenId.
What i want is to transfer all data of "ContactInfo" table to the mysql database system at some server (means server has also a table similar to "ContactInfo", where all data of "ContactInfo" will be copied).
The last important thing which i want is that, whenever i want to get contacts(of a specified TokenId) i can backup all those from server to the mobile device in an xml file.
in short, can here anyone help me how to transfer sqlite db to a web server?
One way is to submit data to your webiste's php page by using GET or POST method which will add it to MySql on your remote application server, like
HttpGet request = new HttpGet(url);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
HttpClient client = new DefaultHttpClient();
String response = client.execute(request, responseHandler);
url can be: www.mysite.com?id=5&name=john ...
This also has to be an AsyncTask doInBackground request...
The problem is how many records can be uploaded at once...
It easy to make the remote application server produce an XML file on request to be downloaded by android, with a similar request like above.
This is an example how to upload an XML file from http://w3mentor.com/learn/java/android-development/android-http-services/example-of-multipart-post-using-android/
Where data.xml file and two more fields ("one" and "two") are uploaded to the server. Note that this will require additional jar libraries which you need to download and place in the "lib" folder on the same level as "res" and and "src" folders in the project.
Here are the three jar files you need httpmime-4.0.jar, apache-mime4j-0.6.jar, commons-io-1.4.jar:
http://james.apache.org/download.cgi#Apache_Mime4J
https://repository.apache.org/content/repositories/releases/org/apache/httpcomponents/httpmime/4.0.1/httpmime-4.0.1.jar
http://code.google.com/p/mapmap/downloads/detail?name=commons-io-1.4.jar&can=2&q=
You add this to the project by selecting the project in Exclipse and click File>Properties>Java Build Path>Libraries and then [Add jars]
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.InputStreamBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
public class TestMultipartPost extends Activity
{
public void executeMultipartPost()throws Exception
{
try {
InputStream is = this.getAssets().open("data.xml");
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("http://w3mentor.com/Upload.aspx");
byte[] data = IOUtils.toByteArray(is);
InputStreamBody isb = new InputStreamBody(new ByteArrayInputStream(data),"uploadedFile");
StringBody sb1 = new StringBody("someTextGoesHere");
StringBody sb2 = new StringBody("someTextGoesHere too");
MultipartEntity multipartContent = new MultipartEntity();
multipartContent.addPart("uploadedFile", isb);
multipartContent.addPart("one", sb1);
multipartContent.addPart("two", sb2);
postRequest.setEntity(multipartContent);
HttpResponse res = httpClient.execute(postRequest);
res.getEntity().getContent().close();
} catch (Throwable e)
{
// handle exception here
}
}
}
One more thing, you need to run this in the "background" as an asynchronous task like this:
private class XmlUploadTask extends AsyncTask<Object, String, Boolean> {
private static final String DEBUG_TAG = "XmlUploadTask";
ProgressDialog pleaseWaitDialog;
#Override
protected void onCancelled() {
Log.i(DEBUG_TAG, "onCancelled");
pleaseWaitDialog.dismiss();
}
#Override
protected void onPostExecute(Boolean result) {
Log.i(DEBUG_TAG, "onPostExecute");
pleaseWaitDialog.dismiss();
}
#Override
protected void onPreExecute() {
pleaseWaitDialog = ProgressDialog.show(myActivity.this, "My Application", "Uploading data...", true, true);
pleaseWaitDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
XmlUploadTask.this.cancel(true);
}
});
}
#Override
protected Boolean doInBackground(Object... params) {
//here you enter the xml upload code above
return null;
}
}
Another way which i found over web that how to send xml file to a web server:
For this you need to add a jar file "commons-httpclient.jar" in your project. (How to add jar file is clearly mentioned by ChristianB in above/below post)
You can download this jar file from http://www.java2s.com/Code/Jar/ABC/Downloadcommonshttpclientjar.htm
2.code would be...
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import java.io.File;
import java.io.FileInputStream;
class ClassName extends Activity
{
public void Sync(View v) // on button click
{
File xmlFile = new File("sdcard/contacts.xml");
FileInputStream fis = new FileInputStream(xmlFile);
InputStreamRequestEntity isre = new InputStreamRequestEntity(fis);
/*now pass url of server in constructor of PostMethod*/
PostMethod post = new PostMethod("http://w3mentor.com/Upload.aspx");
post.setRequestEntity(isre);
post.setRequestHeader("Content-Type", "text/xml");
HttpClient httpclient = new HttpClient();
int response = httpclient.executeMethod(post);
String res = post.getResponseBodyAsString();
Toast.makeText(GetContacts.this, new Integer(response).toString()+" "+res, Toast.LENGTH_LONG).show();
post.releaseConnection();
}
}

Categories

Resources