How to use HttpURLConnection in an Android app? - java

I have a problem in my Android app.
I use a login portal generated by an activity Login Activity, and I want to send username and password to my web API. So I created a java class who use HttpURLConnection for contacting my API. This class was tested (with Netbeans) and everything work perfectly !
But when I call my function who connecting at the API in my Android app, nothing, any request is send. I added Internet permission in androidManifest, always nothing
androidManifest.xml :
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ben.myapp">
<!-- Autorisation -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
.....
</manifest>
My java class :
public static String verifyLoginAndGetData (String userMail, String userPassword) throws IOException {
URL urlGetRequest = new URL("http://my.api.com/index?param1...");
// HTTP Connexion
HttpURLConnection apiConnexion = (HttpURLConnection) urlGetRequest.openConnection();
// Method
apiConnexion.setRequestMethod("GET");
try {
// Response code
int responseCode = apiConnexion.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
// Read the response
BufferedReader in = new BufferedReader(new InputStreamReader(apiConnexion.getInputStream()));
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// Return response
return response.toString();
} else {
return "false";
}
} finally {
apiConnexion.disconnect();
}
} catch (Exception e){
Log.i("Exception", e.toString());
return "false";
}
Where I call this function :
public class LoginDataSource {
public Result<LoggedInUser> login(String username, String password) {
String resultAPI = my_class.verifyLoginAndGetData(username, password);
}
}
variables username and password are not empty.
what am I supposed to use ? Or what i should do ?
Thank you for helping me :)
BenjaminFB

First of all have this run on a separate thread from the ui if not done already,for this id do this
new Thread(new Runnable() {
#Override
public void run() {
try {
Log.e("Download ",verifyLoginAndGetData("username","password"));
} catch (IOException e) {
Log.e("Exception ",""+e.getMessage());
}
}
}).start();
Next thing.am not sure about the api you are dealing with however id
recommend using a network config file to allow cleartext traffic to
your site if it uses cleartext traffic and specify it on your application in manifest.
Another thing, remember the internet permission on your manifest
Other than that,for me this works with the google url www.google.com using get
public static String verifyLoginAndGetData (String userMail, String userPassword) throws IOException {
URL urlGetRequest = new URL("http://www.google.com");
// HTTP Connexion
HttpURLConnection apiConnexion = (HttpURLConnection) urlGetRequest.openConnection();
// Method
apiConnexion.setRequestMethod("GET");
try {
// Response code
int responseCode = apiConnexion.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
// Read the response
BufferedReader in = new BufferedReader(new InputStreamReader(apiConnexion.getInputStream()));
StringBuffer response = new StringBuffer();
String inputLine = null;
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// Return response
return response.toString();
} else {
return "false";
}
} finally {
Log.e("Disconnection", "e.toString()");
apiConnexion.disconnect();
}
}
To return data to another class or to the activity thread, yo can use a handler or interface .below is how i would use an interface
interface data_inter{
void onDataReceived(String data);
}
data_inter inter=new data_inter() {
#Override
public void onDataReceived(String data) {
Log.e("Downloaded: ",data);
Toast.makeText(cntx,"Downloaded: "+data,Toast.LENGTH_LONG).show();
((EditText)findViewById(R.id.focuser)).setText("Downloaded: "+data);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cntx=this;
new Thread(new Runnable() {
#Override
public void run() {
try {
String responce=verifyLoginAndGetData("","");
runOnUiThread(new Runnable() {
#Override
public void run() {
inter.onDataReceived(responce);
}
});
} catch (IOException e) {
Log.e("Exception ",""+e.getMessage());
}
}
}).start();}

Yes it work !!
I did what #code-demon told me to do :
Add at the Manifest
android:usesCleartextTraffic="true"
And use thred but I couldn't get any value back from API response, so I did research and came across it: stackoverflow post.
Finally I developed that :
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<String> callable = new Callable<String>() {
#Override
public String call() throws IOException {
// Call my API get function
return verifyLoginAndGetData(username, password);
}
};
Future<String> future = executor.submit(callable);
executor.shutdown();
// Get in String, the API response
String resultAPI = future.get();

Related

how to get data from url in android studio

I want to get data from url and show in a textView , But after receiving, it only shows html codes.
I use a Educational video but my result is wrong.
I used another methods too but all result are same and just show html codes.
MainActivity :
public static final String SAMPLE_URL = "http://nimatest.epizy.com/ffff.json";
findViewById(R.id.btn_get_data).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new TaskGetData().execute(SAMPLE_URL);
}
});
public class TaskGetData extends AsyncTask<String , String , String>{
#Override
protected void onPreExecute() {
textView.append("Get data ...\n\n");
}
#Override
protected String doInBackground(String... params) {
return MyHttpUtils.getDataHttpUriConnection(params[0]);
}
#Override
protected void onPostExecute(String result) {
textView.append(result + "\n");
}
}
MyHttpUtils :
public static String getDataHttpUriConnection(String uri){
try {
URL url = new URL(uri);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
String result = inputStreamToString(con.getInputStream());
return result;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static String inputStreamToString(InputStream stream) {
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder sb = new StringBuilder();
String line = "";
try
{
while ((line = reader.readLine()) != null)
{
sb.append(line);
sb.append("\n");
}
return sb.toString();
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
Your code is fine. It reads HTML from a URL
This site requires Javascript to work
HttpUrlConnection does not use or render dynamic Javascript created web pages, only static html content
Try a different endpoint for JSON data...
Also, please look into using a proper HTTP library for Android rather than using AsyncTask like Okhttp or Volley

Cannot get http response when intervally requesting a new http request

I have a class called App which is this one:
public class App{
public static void main(String[] args){
StreamingData dataStream = new StreamingData("urlString");
dataStream.StreamHttpRequest();
}
}
and this class called StreamingData that has two methods, the StreamHttpRequest that intervally calls the httpRequest every 1 second as shown below:
public class StreamingData {
private String url;
private JSONObject httpResponse;
public StreamingData(String url){
this.url = url;
}
public void httpRequest() throws Exception{
try {
URL obj = new URL(this.url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
BufferedReader in = new BufferedReader(new
InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
setHttpResponse(new JSONObject(response.toString()));
} catch (ConnectException e){
e.printStackTrace
}
}
public void setHttpResponse(JSONObject httpResponse) {
this.httpResponse = httpResponse;
}
public JSONObject getHttpResponse() {
System.out.println(this.httpResponse.toString());
return this.httpResponse;
}
public void StreamHttpRequest() {
final long timeInterval = 1000;
Runnable runnable = new Runnable() {
public void run() {
while(true){
try {
httpRequest();
} catch (Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(timeInterval);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
Whenever I call the getHttpResponse from the httpRequest method, or pretty much every method from the StreamingData class it returns the whole json response, but when I try to retrieve it from the App class like this
// code as shown above
StreamingData netDataStream = new StreamingData("urlString");
JSONObject netDataHttpResponse = netDataStream.getHttpResponse();
it returns Exception in thread "main" java.lang.NullPointerException and the json is empty.
How can I get the json response to another class (e.g. the App)? Because for now I cannot use it outside the StreamingData class.
Thank you very much for your help,
csymvoul
You're working with threads. That means that the httpResponse field value will be set once the http request performs (async).
here:
StreamingData netDataStream = new StreamingData("urlString");
JSONObject netDataHttpResponse = netDataStream.getHttpResponse();
You're asking for the response immediatelly (when the http response is not ready).
You could add some kind of listener to your StreamingData class , so that you can call on some method when the response is ready:
public class HttpResponseListener {
void onResponse(JSONObject httpResponse){...}
}
Then you could do something like...
StreamingData netDataStream = new StreamingData("urlString" , new HttpResponseListener());
And call httpResponseListener.onResponse when the httpResponse object is set.
public void setHttpResponse(JSONObject httpResponse) {
this.httpResponse = httpResponse;
httpResponseListener.onResponse(httpResponse);
}
That is if you still want to use Http request / reponses with threads.

How to create library for GCM, library creation does not work

I'm trying to create a library for my apps, in all my apps have push notification.
I would like to take this package and create a library
In GCM do I have any limitations? Because it looks like it gets the package name to generate ID_TOKEN
I have an APP that has a package with the classes I use for PUSH notification, it works perfectly!
Now I've migrated this package and created a library, because so all other apps are just pointing the lib and it will be working.
Only that for some reason he does not call the lib, I've done everything and I can not.
The code to register the ID in GCM and start the service is this below:
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
This code above is in my MainActivity
I thought that by doing so he would already call the library
EDIT:
I am using Eclipse and GCM
My class `RegistrationIntentService`
public class RegistrationIntentService extends IntentService {
private static final String TAG = "RegServicePush";
String newRegID = "";
String GetEmail = "";
public RegistrationIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
try {
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(Constants.GCM_SENDER_ID, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
// TODO: Implement this method to send any registration to your
// app's servers.
sendRegistrationToServer(token, email);
} catch (Exception e) {
Log.d(TAG, "Failed to complete token refresh", e);
}
// Notify UI that registration has completed, so the progress indicator
// can be hidden.
}
private void sendRegistrationToServer(String token, String email) {
//MainActivity.newRegID = token;
WebServerRegistrationTask webServer = new WebServerRegistrationTask();
webServer.execute();
}
public class WebServerRegistrationTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(RegistrationIntentService.this);
URL url = null;
try {
url = new URL(Constants.WEB_SERVER_URL);
} catch (MalformedURLException e) {
e.printStackTrace();
sharedPreferences.edit().putString(Constants.PREF_GCM_REG_ID, "").apply();
}
Map<String, String> dataMap = new HashMap<String, String>();
dataMap.put("regID", newRegID);
dataMap.put("appID", Constants.APP_ID);
StringBuilder postBody = new StringBuilder();
Iterator<Map.Entry<String, String>> iterator = dataMap.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, String> param = (Entry<String, String>) iterator.next();
postBody.append(param.getKey()).append('=').append(param.getValue());
if (iterator.hasNext()) {
postBody.append('&');
}
}
String body = postBody.toString();
byte[] bytes = body.getBytes();
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setFixedLengthStreamingMode(bytes.length);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
OutputStream out = conn.getOutputStream();
out.write(bytes);
out.close();
String response = "";
InputStream is = null;
try {
is = conn.getInputStream();
int ch;
StringBuffer sb = new StringBuffer();
while ((ch = is.read()) != -1) {
sb.append((char) ch);
}
response = sb.toString();
} catch (IOException e) {
throw e;
} finally {
if (is != null) {
is.close();
}
}
int status = conn.getResponseCode();
if (status == 200) {
if (response.equals("1")) {
sharedPreferences.edit().putString(Constants.PREF_GCM_REG_ID, newRegID).apply();
Intent registrationComplete = new Intent(Constants.SERVER_SUCCESS);
LocalBroadcastManager.getInstance(RegistrationIntentService.this)
.sendBroadcast(registrationComplete);
}
} else {
throw new IOException("Request failed with error code " + status);
}
} catch (ProtocolException pe) {
pe.printStackTrace();
sharedPreferences.edit().putString(Constants.PREF_GCM_REG_ID, "").apply();
} catch (IOException io) {
io.printStackTrace();
sharedPreferences.edit().putString(Constants.PREF_GCM_REG_ID, "").apply();
} finally {
if (conn != null) {
conn.disconnect();
}
}
return null;
}
}
}

How pass method in AsyncTask?

I've class with methods
class Wrapper {
public static String AuthIn(String Login, String Password){
String response = HTTPRequest.POST(client, GetAuthUrl(), RequestBuilder.AuthInVk(login, password));
System.out.println(response);
}
public static String GetInfoUser(){
String response = HTTPRequest.GET(client, "http://site1.com");
System.out.println(response);
}
}
When i call this methods in MainActivity class and get error message "Main thread ..... etc"
How write Wrapper class in AsyncTask ?
Here is a nice example taken from codexpedia, for more details please check their site.
public class MainActivity extends AppCompatActivity {
TextView tvWeatherJson;
Button btnFetchWeather;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvWeatherJson = (TextView) findViewById(R.id.tv_weather_json);
btnFetchWeather = (Button) findViewById(R.id.btn_fetch_weather);
btnFetchWeather.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new FetchWeatherData().execute();
}
});
}
private class FetchWeatherData extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String forecastJsonStr = null;
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page, at
// http://openweathermap.org/API#forecast
URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7&appid=2de143494c0b295cca9337e1e96b00e0");
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
forecastJsonStr = buffer.toString();
return forecastJsonStr;
} catch (IOException e) {
Log.e("PlaceholderFragment", "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
tvWeatherJson.setText(s);
Log.i("json", s);
}
}
}
If you want to pass data into the async task doInBackground or onPostExcute and more check this stackoverflow comment : what-arguments-are-passed-into-asynctaskarg1-arg2-arg3
Keep in mind that your AsyncTask won't stop even when the activity has destroyed. A better way to create a network call from an activity is with an Handler Or just use an asyncHttp client lib such as ok-http , google volley :)
You always must perform network request form other thread than UI thread. So you can create abstarct class (network dispatcher) which extend AsyncTask or Thread or Runnable and add abstarct method which will be called in run/doInBackground/etc. Next implement abstarct method in your method. But it a little improvement to your boilerplate code. Also you can use JavaRx (AndroidRx) to perform networking method. Also you can use Retrofit with JavaRx.
EDIT
I see you edit your question. If you want use AsyncTask you should implement it and perform request in doInBackgroud

Using AsyncTask with passing a value

I have been working on this and I have hit a point where I dont know what to do. What I am trying to do is use one class to download and parse out a file into a string and then send that string to another class to parse out the JSON stuff. All the parts work fine by themselves and I have tested everything separately. I just dont know how to send the value to the Json parses to start the parsing.
So this is my filedownloader class.
public class JsonFileDownloader extends AsyncTask<String, Void, String> {
//used to access the website
String username = "admin";
String password = "admin";
public String ret = "";
#Override
protected String doInBackground(String... params) {
Log.d("Params ", params[0].toString());
readFromFile(params[0]);
return ret;
}
private String readFromFile(String myWebpage) {
HttpURLConnection urlConnection = null;
try {
//Get the url connection
URL url = new URL(myWebpage);
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
});
urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
if (inputStream != null) {
ret = streamToString(inputStream);
inputStream.close();
Log.d("Final String", ret);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
return ret;
}
}
public static String streamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
return sb.toString();
}
public String getJsonData()
{
return ret;
}
}
This works fine I have tested it over and over with no errors.
The next is the Json parser which is like this.
public class JSONParser {
JSONObject jsonResponse;
String jsonData;
//Consturctor
public JSONParser()
{
//this.jsonData = jsonData;
// this.OutputData = outPutData;
}
public void parsesData(String promo,
ArrayList<String> pictureHTTP,
ArrayList<String> pathHTTP,
ArrayList<String> labelText) throws IOException {
//Build the Json String
JsonFileDownloader jfd = new JsonFileDownloader();
// jsonData = String.valueOf(jfd.execute(promo));
jfd.execute(promo);
//jfd.getResuts(jsonData);
//jsonData = jfd.ret;
Log.d("JsonData String = " , jsonData);
//Try to parse the data
try
{
Log.d("Jsondata " , jsonData);
//Creaate a new JSONObject ith the name/value mapping from the JSON string
jsonResponse = new JSONObject(jsonData);
//Returns the value mapped by the name if it exists and is a JSONArry
JSONArray jsonMainNode = jsonResponse.optJSONArray("");
//Proccess the JSON node
int lenghtJsonArrar = jsonMainNode.length();
for (int i = 0; i<lenghtJsonArrar; i++)
{
//Get object for each json node
JSONObject jsonChildNode = jsonMainNode.getJSONObject(i);
//Get the node values
//int song_id = Integer.parseInt(jsonChildNode.optString("song_id").toString());
String picture = jsonChildNode.optString("picture").toString();
String pathName = jsonChildNode.optString("path").toString();
String lableName = jsonChildNode.optString("label".toString());
//Debug Testing code
pictureHTTP.add(picture);
pathHTTP.add(pathName);
labelText.add(lableName);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
Now I know where the problem is occurring. When i try to assign a value to the jsonData it never is assigned so it is null and the system fails.
I have tried a few things after the jfd.exicute() but I just dont know how to get the value from the final string output into the jsonData.
Thank you for any help with this.
Alright, here is a pretty flexible pattern for the overall usage of using AsyncTask to download web content and getting the results from it back to the UI thread.
Step 1 Define an interface that will act as a message bus between the AsyncTask and where you want the data.
public interface AsyncResponse<T> {
void onResponse(T response);
}
Step 2 Create a generic AsyncTask extension that will take any URL and return the results from it. You basically had this already, but I made some tweaks. Most importantly, allowing the setting of the AsyncResponse callback interface.
public class WebDownloadTask extends AsyncTask<String, Void, String> {
private AsyncResponse<String> callback;
// Optional parameters
private String username;
private String password;
// Make a constuctor to store the parameters
public WebDownloadTask(String username, String password) {
this.username = username;
this.password = password;
}
// Don't forget to call this
public void setCallback(AsyncResponse<String> callback) {
this.callback = callback;
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
return readFromFile(url);
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (callback != null) {
callback.onResponse(s);
} else {
Log.w(WebDownloadTask.class.getSimpleName(), "The response was ignored");
}
}
/******* private helper methods *******/
private String streamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
return sb.toString();
}
private String readFromFile(String myWebpage) {
String response = null;
HttpURLConnection urlConnection = null;
try {
//Get the url connection
URL url = new URL(myWebpage);
// Unnecessary for general AsyncTask usage
/*
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
});
*/
urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
if (inputStream != null) {
response = streamToString(inputStream);
inputStream.close();
Log.d("Final String", response);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return response;
}
}
Step 3 Go forth and use that AsyncTask wherever you wish. Here is an example. Note that if you do not use setCallback, you will be unable to get the data that came from the AsyncTask.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebDownloadTask task = new WebDownloadTask("username", "password");
task.setCallback(new AsyncResponse<String>() {
#Override
public void onResponse(String response) {
// Handle response here. E.g. parse into a JSON object
// Then put objects into some list, then place into an adapter...
Toast.makeText(getApplicationContext(), response, Toast.LENGTH_SHORT).show();
}
});
// Use any URL, this one returns a list of 10 users in JSON
task.execute("http://jsonplaceholder.typicode.com/users");
}
}

Categories

Resources