How to manage multiple AsyncTasks in Android - java

I want to create my AsyncTask in separated classes because of I have to parse XML and it's a bunch of code.
So I want to get noticed in the activity everytime an asynctask is completed.
I followed this question
The problem is that when I have to make multiple petitions, everytime one is completed call the same method.
I want to call different methods depending of the AsyncTask Class I called.
EDIT: One of my AsyncTask Classes
public class FichaProducto extends AsyncTask<Void,Void,String>{
private String codigo, descripcion, ubicacion, descPromocion, currentUser,ip,port,codigoBuscar, respuesta;
private float precio;
private static final String TAG = "Logger";
private OnTaskCompleted listener;
/**
* Without listener
* #param codigoBuscar
* #param currentUser
* #param ip
* #param port
*/
public FichaProducto(String codigoBuscar,String currentUser,String ip,String port) {
setCodigoBuscar(codigoBuscar);
setCurrentUser(currentUser);
setIp(ip);
setPort(port);
}
/**
* With listener
* #param codigoBuscar
* #param currentUser
* #param ip
* #param port
* #param listener
*/
public FichaProducto(String codigoBuscar, String currentUser, String ip, String port, OnTaskCompleted listener) {
setCodigoBuscar(codigoBuscar);
setCurrentUser(currentUser);
setIp(ip);
setPort(port);
this.listener = listener;
}
/**
* set the xml response
* #param response
*/
public void setRespuesta(String respuesta) {
this.respuesta = respuesta;
}
/**
* #return server xml response
*/
#Override
protected String doInBackground(Void... params) {
StringBuilder respuesta = new StringBuilder();
URL url;
HttpURLConnection conexion = null;
try{
//Create the connection and set parameters
url = new URL("http://"+getIp()+":"+getPort());
Log.d(TAG,url.toString());
conexion = (HttpURLConnection)url.openConnection();
conexion.setRequestMethod("POST");
conexion.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conexion.setRequestProperty("Content-Length", "" + Integer.toString(getXML().getBytes().length));
conexion.setRequestProperty("Content-Language", "es-ES");
conexion.setUseCaches(false);
conexion.setDoInput(true);
conexion.setDoOutput(true);
//Send the petition
DataOutputStream dos = null;
dos = new DataOutputStream(conexion.getOutputStream());
dos.writeBytes(getXML());
dos.flush();
dos.close();
//Get the response
InputStream is = conexion.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String linea;
while ((linea = br.readLine()) != null){
respuesta.append(linea);
respuesta.append("\n");
}
br.close();
Log.d(TAG,"From asynctask the response is: "+respuesta.toString());
return respuesta.toString();
}catch(MalformedURLException e){
Log.e(TAG,"MalformedURLException in AsyncTask "+e.getMessage());
return null;
}catch (IOException e){
Log.e(TAG,"IO Exception in AsyncTask "+e.getMessage());
return null;
} finally {
//Close the connection
if (conexion != null){
conexion.disconnect();
}
}
}
/**
* Set the response and call the listener
*/
#Override
protected void onPostExecute(String respuesta){
setRespuesta(respuesta);
//Here it'll read the xml received and will set the variables
if (listener != null){
listener.onTaskCompleted();
}
}
(If it's bad, excuse my english pls)

To check which task is compelte you can use follow:
Update OnTaskCompleted with onTaskCompleted(int id);
private OnTaskCompleted listener;
private int id;
public FichaProducto(String codigoBuscar, String currentUser, String ip,
String port, OnTaskCompleted listener, int id) {
setCodigoBuscar(codigoBuscar);
setCurrentUser(currentUser);
setIp(ip);
setPort(port);
this.listener = listener;
this.id = id
}
#Override
protected void onPostExecute(String respuesta){
setRespuesta(respuesta);
//Here it'll read the xml received and will set the variables
if (listener != null){
listener.onTaskCompleted(id);
}
}
In activity class you can use something like this:
private final int PARSE_XML = 0
private final int PARSE_JSON = 1
void parseXml(){
new FichaProducto(codigoBuscar, currentUser, ip, port, PARSE_XML)
}
#Override
onTaskCompleted(int id){
switch (id){
case PARSE_XML:
break;
case PARSE_JSON:
break;
}
}

Related

problem recived the earthquake JSON result

This Is the Error:-
E/QueryUtils: problem recived the earthquake JSON result
java.net.ProtocolException: Expected one of [OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, PATCH] but was Get
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.setRequestMethod(HttpURLConnectionImpl.java:606)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.setRequestMethod(DelegatingHttpsURLConnection.java:113)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.setRequestMethod(HttpsURLConnectionImpl.java)
at com.example.quakereport.QueryUtils.makeHttpRequest(QueryUtils.java:92)
at com.example.quakereport.QueryUtils.featchEarthquakeDate(QueryUtils.java:52)
at com.example.quakereport.MainActivity$EarthquakeAsyncTask.doInBackground(MainActivity.java:64)
at com.example.quakereport.MainActivity$EarthquakeAsyncTask.doInBackground(MainActivity.java:56)
at android.os.AsyncTask$2.call(AsyncTask.java:304)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:760)
MainActivity.java
public class MainActivity extends AppCompatActivity {
private EarthquakeAdapter mAdapter;
//URL for earthquake data from the USGS dataset
private static final String USGS_REQUEST_URL ="https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&eventtype=earthquake&orderby=time&minmag=6&limit=10";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/** Find a refrence to the {#link ListView} in the layout*/
ListView eathquakeListView = (ListView) findViewById(R.id.list);
/** Create a new {#link ArrayAdapter} of earthquakes*/
mAdapter = new EarthquakeAdapter(this,new ArrayList<Earthquake>());
eathquakeListView.setAdapter(mAdapter);
/** Start the AsyncTask to fetch the earthquake data*/
EarthquakeAsyncTask task = new EarthquakeAsyncTask();
task.execute(USGS_REQUEST_URL);
eathquakeListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
// Find the current earthquake that was clicked on
Earthquake currentEarthquake = mAdapter.getItem(position);
//convert the String URL int a URI object(to pass into the intent constructor)
Uri eathquakeuri = Uri.parse(currentEarthquake.getmUrl());
//Create a new intent to view the earthquake URI
Intent websiteIntent = new Intent(Intent.ACTION_SEND, eathquakeuri);
// Send the intent to launch a new activity
startActivity(websiteIntent);
}
});
}
private class EarthquakeAsyncTask extends AsyncTask<String, Void, List<Earthquake>>{
protected List<Earthquake> doInBackground(String... urls) {
/** If there is a valid list of {#link Earthquake}, then add them to the adapter's data set. This will trigger the
* Listview to update*/
if(urls.length<1 || urls[0] == null){
return null;
}
List<Earthquake> result = QueryUtils.featchEarthquakeDate(urls[0]);
return result;
}
#Override
protected void onPostExecute(List<Earthquake> data) {
/** Clear the adapter of previous earthquake data*/
mAdapter.clear();
/** If there is a valid list of {#link Earthquake}s, then add them to the adapter's dataset. THis will trigger
* the ListVIew to update*/
if (data != null && !data.isEmpty()){
mAdapter.addAll(data);
}
}
}
}
QueryUtils.java
public final class QueryUtils {
/**
* Sample JSON response for a USGS query
*/
/**
* Create a private constructor because no one should ever create a {#link QueryUtils} object.
* This class is only meant to hold static variables and methods, which can be accessed
* directly from the class name QueryUtils (and an object instance of QueryUtils is not needed).
*/
private static final String LOG_TAG = QueryUtils.class.getSimpleName();
private QueryUtils() {
}
/**
* Query the USGS dataset and return a list of{#link Earthquake} objects.
*/
public static List<Earthquake> featchEarthquakeDate(String requestUrl)
{
// Create URL Object
URL url = createurl(requestUrl);
// Perform HTTP request to the URL and recive a JSON response back
String JSONResponse = null;
try{
JSONResponse = makeHttpRequest(url);
}catch (IOException e)
{
Log.e(LOG_TAG,"Problem Making http equest", e);
}
// Extract relevent fields fom the JSON response and create a list of {#link Earthquake}s
List<Earthquake> earthquakes = extractFeatureFromJson(JSONResponse);
//Return the list of {#link Earthquake}s
return earthquakes;
}
/**
* Return new URL from object from the given string URL
*/
private static URL createurl(String stringURL){
URL url = null;
try {
url = new URL(stringURL);
}catch (MalformedURLException e){
Log.e(LOG_TAG,"problem building the url", e);
}
return url;
}
/**
* Make an HTTP request to the given URL and return a string as the response.
* */
private static String makeHttpRequest(URL url)throws IOException{
String jsonResponse = "";
// If the URL is null, then return early.
if (url == null){
return jsonResponse;
}
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try{
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(10000/* millisecond*/);
urlConnection.setConnectTimeout(15000 /*milisecond*/);
urlConnection.setRequestMethod("Get");
urlConnection.connect();
//If the request was successful (response code 200), then read the Input Stream and parse the Response.
if (urlConnection.getResponseCode() == 200){
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
}else {
Log.e(LOG_TAG,"Error Response code" + urlConnection.getResponseCode());
}
}catch (IOException e){
Log.e(LOG_TAG,"problem recived the earthquake JSON result",e);
}finally {
if (urlConnection!=null)
{
urlConnection.disconnect();
}
if (inputStream!=null){
/*
Closing the input Stream could throw an IOException, which is why the makeHttpRequest(URL url) method
signature specific than an IOException could be thrown.
*/
inputStream.close();
}
}
return jsonResponse;
}
private static String readFromStream(InputStream inputStream) throws IOException{
StringBuilder output = new StringBuilder();
if (inputStream != null){
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null){
output.append(line);
line = reader.readLine();
}
}
return output.toString();
}
/**
* Return a list of {#link Earthquake} objects that has been built up from
* parsing a JSON response.
*/
private static List<Earthquake> extractFeatureFromJson(String eartheuakeJSON) {
// If the JSON string is empity or null, then return early.
if (TextUtils.isEmpty(eartheuakeJSON))
{
return null;
}
// Create an empty ArrayList that we can start adding earthquakes to
List<Earthquake> earthquakes = new ArrayList<Earthquake>();
// Try to parse the JSON response string. If there's a problem with the way the JSON
// is formatted, a JSONException exception object will be thrown.
// Catch the exception so the app doesn't crash, and print the error message to the logs.
try {
// create a JSONObject from the JSON response string
JSONObject baseJsonResponse = new JSONObject(eartheuakeJSON);
// Extract the JSONArray associated with the key called "features", which represent a list of features(or earthquakes).
JSONArray earthquakeArray = baseJsonResponse.getJSONArray("features");
// For each earthquake in the earthquakeArray, create an {#link Earthquake} object
for (int i = 0; i < earthquakeArray.length(); i++) {
JSONObject currentEarthquake = earthquakeArray.getJSONObject(i);
// For a given earthquake, extract the JSONObject associated with the key called "properties", which represent a
// list of all properties for the earthquake.
JSONObject properties = currentEarthquake.getJSONObject("properties");
// Extract the value for the key called "mag"
Double magnitude = properties.getDouble("mag");
// Extract the value for the key called "place"
String location = properties.getString("place");
// Extract the value for the key called "time"
long time = properties.getLong("time");
// Extract the value for the key called "url"
String url = properties.getString("url");
// Create a new {#link Earthquake} object with the magnitude,locaton,time, and url
// from the JSON response
Earthquake earthquake = new Earthquake(magnitude, location, time,url);
// Add the new {#link Earthquake} to the list of earthquakes.
earthquakes.add(earthquake);
}
} catch (JSONException e) {
// If an error is thrown when executing any of the above statements in the "try" block,
// catch the exception here, so the app doesn't crash. Print a log message
// with the message from the exception.
Log.e("QueryUtils", "Problem parsing the earthquake JSON results", e);
}
// Return the list of earthquakes
return earthquakes;
}
}
Earthquake.java
package com.example.quakereport;
import android.content.Context;
public class Earthquake {
private Double mMagnitude;
private String mLocation;
private String mDate;
private long mTimeInMillisecond;
private String mUrl;
public Earthquake(Double Magnitude, String Location, long TimeInMIllisecond, String Url) {
mMagnitude = Magnitude;
mLocation = Location;
mTimeInMillisecond = TimeInMIllisecond;
mUrl = Url;
}
public Double getmMagnitude() {
return mMagnitude;
}
public String getmLocation() {
return mLocation;
}
public String getmUrl() {
return mUrl;
}
public long getmTimeInMillisecond() {
return mTimeInMillisecond;
}
}
EartquakeAdapter.java
public class EarthquakeAdapter extends ArrayAdapter<Earthquake> {
private static final String LOCATION_SEPARATOR = "of";
public EarthquakeAdapter (Context context, List<Earthquake> place)
{
super(context,0,place);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View listItemView = convertView;
if (listItemView == null)
{
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.earthquake_list_item,parent,false);
}
Earthquake currentEarthQuake = getItem(position);
TextView magnitude = (TextView) listItemView.findViewById(R.id.magnitude);
// Formate The Magnitude to show 1 decimal place
String formattedMaginitude = formatedMagnitude(currentEarthQuake.getmMagnitude());
magnitude.setText(formattedMaginitude);
//Set the prope background color on the magnitude circle.
// Fetch the background fom the Textview, which is a GadientDrawable.
GradientDrawable maginitudeCircle = (GradientDrawable) magnitude.getBackground();
// Get the appropriate background color based on the current earthquake magnitude
int magnitudeColor = getMagnitudeColor(currentEarthQuake.getmMagnitude());
// Set the color on the magnitude cicle
maginitudeCircle.setColor(magnitudeColor);
String originallocation = currentEarthQuake.getmLocation();
String primaryLocation;
String locationOffset;
if(originallocation.contains(LOCATION_SEPARATOR))
{
String[] parts = originallocation.split(LOCATION_SEPARATOR);
locationOffset = parts[0] + LOCATION_SEPARATOR;
primaryLocation = parts[1];
}else {
locationOffset= getContext().getString(R.string.near_the);
primaryLocation = originallocation;
}
TextView primarrylocation = (TextView) listItemView.findViewById(R.id.location_primarry);
primarrylocation.setText(primaryLocation);
TextView locationOffsetView = (TextView) listItemView.findViewById(R.id.location_offset);
locationOffsetView .setText(locationOffset);
// TextView locationView = (TextView) listItemView.findViewById(R.id.location_primarry);
// locationView.setText(currentEarthQuake.getmLocation());
Date dateObject = new Date(currentEarthQuake.getmTimeInMillisecond());
TextView dateView = (TextView) listItemView.findViewById(R.id.date);
// Fomate the date string (ex "Mar 3, 1995")
String formattedDate = formatDate(dateObject);
dateView.setText(formattedDate);
TextView timeView = (TextView) listItemView.findViewById(R.id.time);
String formattedtime = formatTime(dateObject);
timeView.setText(formattedtime);
return listItemView;
}
private int getMagnitudeColor(double magnitude)
{
int mgnitudeColorResourceId;
int magnitudeFloor = (int) Math.floor(magnitude);
switch (magnitudeFloor)
{
case 0:
case 1:
mgnitudeColorResourceId = R.color.magnitude1;
break;
case 2:
mgnitudeColorResourceId = R.color.magnitude2;
break;
case 3:
mgnitudeColorResourceId = R.color.magnitude3;
break;
case 4:
mgnitudeColorResourceId = R.color.magnitude4;
break;
case 5:
mgnitudeColorResourceId = R.color.magnitude5;
break;
case 6:
mgnitudeColorResourceId = R.color.magnitude6;
break;
case 7:
mgnitudeColorResourceId = R.color.magnitude7;
break;
case 8:
mgnitudeColorResourceId = R.color.magnitude8;
break;
case 9:
mgnitudeColorResourceId = R.color.magnitude9;
break;
default:
mgnitudeColorResourceId = R.color.magnitude10plus;
break;
}
return ContextCompat.getColor(getContext(),mgnitudeColorResourceId);
}
private String formatDate(Date dateObject){
SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd, yyyy");
return dateFormat.format(dateObject);
}
private String formatTime (Date dateObject){
SimpleDateFormat timeFormate = new SimpleDateFormat("h:mm a");
return timeFormate.format(dateObject);
}
private String formatedMagnitude(double magnitude){
DecimalFormat magnitudeFormate = new DecimalFormat("0.0");
return magnitudeFormate.format(magnitude);
}
}
In File: QueryUtils.java
You need to change this line of code
urlConnection.setRequestMethod("Get");
To this one
urlConnection.setRequestMethod("GET");
The error message explains it:
This Is the Error:- E/QueryUtils: problem recived the earthquake JSON result java.net.ProtocolException: Expected one of [OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, PATCH] but was Get at
It expected GET but it was Get

Data fetching from an API in android

I have tried to fetch data from an API which has a key. But in the output it says "app key not found".
I have tested it on Postman and it works properly.
Here is my code:
public class fetchData extends AsyncTask<Void,Void,Void> {
String data="";
#Override
protected Void doInBackground(Void... voids) {
try {
URL url=new URL("https://app.inyek.com/app_api/api_extra/all_order.php?");
HttpURLConnection con=(HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded/json;charset=UTF-8");
con.setRequestProperty("app_key","whatever");
con.setDoOutput(true);
}
I strongly suggest you make an Abstract HttpRequestTask which extends AsyncTask. In this abstract ancestor you can make some helper methods for reading your input, something like so:
/**
* HttpRequestTask is an abstract extension of an AsyncTask for HTTP Requests.
*
* #param <P>
* Type for parameter(s) to doInBackground (can be Void if none provided)
* #param <R>
* Type for result of request (can be Void if ignored, or using listeners.)
*/
public abstract class HttpRequestTask<P, R> extends AsyncTask<P, Integer, R>
{
private static final String TAG = "HttpRequestTask";
// Post form encoded requests, get back JSON response
private static final RequestMethod DEFAULT_REQUEST_METHOD = RequestMethod.POST;
private static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded;charset=UTF-8;";
private static final String DEFAULT_ACCEPT = "application/json;";
private static final int DEFAULT_TIMEOUT = 8000; // 8 seconds
private static final String CHARSET = "UTF-8";
protected static final String NULL_CONTEXT = "Context is null.";
protected static final String INVALID_RESPONSE = "The server did not send back a valid response.";
// Request methods supported by back-end
protected enum RequestMethod
{
GET("GET"),
POST("POST");
private final String method;
RequestMethod(String method)
{
this.method = method;
}
#Override
public String toString()
{
return this.method;
}
}
/**
* ALWAYS use application context here to prevent memory leaks.
*
*/
protected HttpRequestTask(#NonNull final Context context)
{
this.context = context;
}
protected void verifyConnection() throws IOException
{
if (!SystemUtil.isInternetAvailable(context))
{
throw new IOException("Internet is unavailable.");
}
}
/**
* Creates and opens a URLConnection for the url parameter, as well as setting request options.
*
* #param url
* to connect to.
*
* #return opened HTTPURLConnection for POSTing data to ctservices.
*/
protected HttpURLConnection getURLConnection(URL url) throws IOException
{
return this.getURLConnection(url, DEFAULT_REQUEST_METHOD, DEFAULT_CONTENT_TYPE,
DEFAULT_ACCEPT, DEFAULT_TIMEOUT);
}
/**
* Creates and opens a URLConnection for the url parameter, as well as setting request options.
*
* #param url
* to connect to.
*
* #return opened HTTPURLConnection
*/
protected HttpURLConnection getURLConnection(#NonNull final URL url,
#NonNull final RequestMethod requestMethod,
#NonNull final String contentType,
#Nullable final String accept, final int timeout)
throws IOException
{
verifyConnection();
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod(requestMethod.toString());
urlConnection.setRequestProperty("Content-Type", contentType);
if (accept != null && !accept.isEmpty())
{
urlConnection.setRequestProperty("Accept", accept);
}
urlConnection.setReadTimeout(timeout);
urlConnection.setConnectTimeout(timeout);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
return urlConnection;
}
/**
* Creates and opens a URLConnection for the url parameter, but does not set any request options.
*
* #param url
* to connect to.
*
* #return opened HTTPURLConnection without parameters set.
*/
protected HttpURLConnection getBasicURLConnection(URL url) throws IOException
{
if (!SystemUtil.isInternetAvailable(applicationContext.get()))
{
throw new IOException("Internet is unavailable.");
}
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
return urlConnection;
}
/**
* Write a JSONObject of request parameters to the output stream as form-encoded data.
*
* #param urlConnection
* opened urlConnection with output enabled (done by getURLConnection).
* #param params
* to write to request.
*
* #throws IOException
* problem writing to output stream
*/
protected void writeParams(HttpURLConnection urlConnection, JSONObject params) throws IOException
{
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter outWriter = new BufferedWriter(new OutputStreamWriter(outputStream,
StandardCharsets.UTF_8));
String urlParams = this.encodeJSONObject(params);
outWriter.write(urlParams);
outWriter.flush();
outWriter.close();
outputStream.close();
}
/**
* Reads the response of a URLConnection from the input stream and puts it in a string.
*
* #param urlConnection
* opened urlConnection with input enabled (done by getURLConnection).
*
* #return response string
*
* #throws IOException
* problem reading input stream
*/
protected String readResponse(HttpURLConnection urlConnection) throws IOException
{
InputStream inputStream = null;
try
{
/* If we failed to connect will throw a SocketResponseTimeoutException,
* which is an IOException. */
int responseCode = urlConnection.getResponseCode();
if (HttpURLConnection.HTTP_OK != responseCode)
{
throw new IOException("Bad response code - " + responseCode);
}
inputStream = urlConnection.getInputStream();
final String response = parseInputStream(inputStream);
urlConnection.disconnect();
return response;
}
finally
{
if (inputStream != null)
{
try
{
inputStream.close();
}
catch (Exception e) {}
}
}
}
protected Context getContext()
{
return this.context;
}
protected String getString(final int resId)
{
return getContext().getString(resId);
}
/**
* Encodes a JSONObject as a form-data URL string.
*
* #param jo
* to encode
*
* #return encoded URL string
*/
private String encodeJSONObject(JSONObject jo)
{
StringBuilder sb = new StringBuilder();
boolean first = true;
Iterator<String> itr = jo.keys();
String key;
Object val;
try
{
while (itr.hasNext())
{
key = itr.next();
val = jo.get(key);
if (first)
{
first = false;
}
else
{
sb.append('&');
}
sb.append(URLEncoder.encode(key, CHARSET));
sb.append('=');
sb.append(URLEncoder.encode(val.toString(), CHARSET));
}
}
catch (JSONException | UnsupportedEncodingException e) {}
return sb.toString();
}
private String parseInputStream(InputStream is) throws IOException
{
BufferedReader br = null;
try
{
br = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null)
{
sb.append(line);
}
return sb.toString();
}
finally
{
if (br != null)
{
try
{
br.close();
}
catch (Exception e) {}
}
}
}
/**
* Merges any properties of b into a that don't already have a key match in a.
*
* #param a
* merging to
* #param b
* merging from
*
* #return a with any unique values from b
*/
protected JSONObject mergeJSONObjects(JSONObject a, JSONObject b)
{
if (b == null)
{
return a;
}
if (a == null)
{
return b;
}
try
{
Iterator<String> bItr = b.keys();
String key;
while (bItr.hasNext())
{
key = bItr.next();
if (!a.has(key))
{
a.put(key, b.get(key));
}
}
return a;
}
catch (Exception ex)
{
Log.e(TAG, ex.getClass().getSimpleName() + " in mergeJSONObjects: " + ex.getMessage() +
'\n' + Log.getStackTraceString(ex));
return a;
}
}
}
Then you can extend your HttpRequestTask to easily make network requests:
public class ExampleNetworkTask extends HttpRequestTask<Void, Void>
{
private static final String TAG = "ExampleNetworkTask";
private final SimpleListener successListener;
private final StringListener errorListener;
private final String servicesUrl;
public static void start(#NonNull final Context context,
#Nullable final SimpleListener successListener,
#Nullable final StringListener errorListener)
throws IllegalArgumentException
{
if (context == null)
{
throw new IllegalArgumentException(NULL_CONTEXT);
}
new ExampleNetworkTask(context, successListener, errorListener).execute();
}
private ExampleNetworkTask(#NonNull final Context context,
#Nullable final SimpleListener successListener,
#Nullable final StringListener errorListener)
{
super(context);
this.servicesUrl = SystemUtil.getServiceUrl(getContext(), R.string.example_service);
this.successListener = successListener;
this.errorListener = errorListener;
}
#Override
protected Void doInBackground(Void... voids)
{
try
{
final HttpURLConnection urlConnection = super.getURLConnection(new URL(servicesUrl));
final JSONObject params = new JSONObject();
// Add params
params.put("app_key", appKey);
params.put("order_number", orderNumber);
// ...
// Send request, read parse response
super.writeParams(urlConnection, params);
final String response = super.readResponse(urlConnection);
final JSONObject responseObj = new JSONObject(response);
// Handle response
}
catch (Exception ex)
{
final String msg = ex.getLocalizedMessage();
Log.e(TAG, ex.getClass().getSimpleName() + ": " + msg + '\n' +
Log.getStackTraceString(ex));
// Handle network exceptions and other exceptions here.
}
return null;
}
}
In PostMan, how did you specify the app key? was it through an HTTP header?
(Sorry, I would have added a comment, but I do not have enough reputation)
Or was it specified as a GET parameter?
In the latter case, try something like:
URL url=new URL("https://app.inyek.com/app_api/api_extra/all_order.php?app_key=YOUR_KEY");
Welcome to Stack Exchange! Firstly I'd suggest you don't put your API Key within questions and/or images, as they might be sensitive and can be abused by malicious users. Feel free to edit your question and remove them.
To answer your query, I think you need to write the contents to the http request body in a json format. This can be done as per the guide on the following webpage:
https://www.baeldung.com/httpurlconnection-post
In summary, you need to create an output stream and write the contents to it directly.
Thank you guys! finally i got the answer using OkHttpClient. here is the code:
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "app_key=whatever");
Request request = new Request.Builder()
.url("https://app.inyek.com/app_api/api_extra/all_order.php")
.post(body)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.addHeader("key", "whatever")
.addHeader("cache-control", "no-cache")
.addHeader("Postman-Token", "whatever")
.build();
Response response = client.newCall(request).execute();

Android tv-guid application

For an assignment I have to make an Android tv-guid app.
The assignment description states:
implement the program.java class according to the instructions in the ProgramInterface.java. Program.java is the datatype to describe programs.
implement the channel.java class according to the instructions in the ChannelInterface.java. Channel.java is the datatype to describe channels.
Implement the ChannelParser.java class according to the instructions in the ChannelParserInterface.java. ChannelParser.java is the object that reads the files and extracts the data to make an Arraylist of the channels.
I think i did workout the first two steps, but I can't get the last step working. Does anybody know what i'm doing wrong. I have attached all the codes.
ChannelInterface.java
public interface ChannelInterface {
/**
* Method that returns the name of this channel, e.g. "Nederland 1".
* #return String channel name.
*/
public String getName();
/**
* Method that returns the list of programs scheduled on this channel.
* #return ArrayList of Programs.
*/
public ArrayList<Program> getPrograms();
/**
* Method to add a program to the list of programs.
* #param program The program that is to be added to the list.
*/
public void addProgram(Program program);
ChannelParserInterface.java
public interface ChannelParserInterface {
/**
* Method invoked by the app to create the list of channels. This method should:
* - read the program details from file (txt/xml)
* - create the <code>ArrayList<Program></code> for each channel
* - create the Channel object for each channel (setting their name and program list)
* - return the list of create Channel objects.
* Before returning the list of Channels, make sure that no gaps exist in the Program Lists of each channels (fill the gaps!).
* #return The ArrayList of Channels.
*/
public ArrayList<Channel> createChannels();
}
ChannelParser.java
public class ChannelParser implements ChannelParserInterface {
/**
* Hulp methode om het bestand van internet in te lezen en als Stream aan te bieden.
* #param type "xml" of "txt" om aan te duiden welk bestand je wilt gebruiken
* #return De InputStream die gelezen kan worden.
*/
private InputStream openStream(String type) {
try {
URL url;
if(type.equals("xml"))
url = new URL("http://ict1.tbm.tudelft.nl/epg.xml");
else
url = new URL("http://ict1.tbm.tudelft.nl/epg.txt");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
return con.getInputStream();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public ArrayList<Channel> createChannels() {
ArrayList<Channel> result = new ArrayList<Channel>();
Scanner input = new Scanner(openStream("txt"));
ArrayList<Program> programlist = new ArrayList<Program>();
Channel nederland1 = new Channel();
Channel nederland2 = new Channel();
Channel nederland3 = new Channel();
Channel rtl4 = new Channel();
Channel rtl5 = new Channel();
Channel sbs6 = new Channel();
Channel rtl7 = new Channel();
Channel net5 = new Channel();
Channel veronica = new Channel();
Channel discovery = new Channel();
result.add(new Channel());
return result;
}
Program.java
public class Program implements ProgramInterface {
public String title, subtitle, description, category, startTime, endTime;
public Program(String title, String subtitle, String description, String category, String startTime, String endTime) {
this.title = title;
this.subtitle = subtitle;
this.description = description;
this.category = category;
this.startTime = startTime;
this.endTime = endTime;
}
public String getTitle() {
return title;
}
public String getSubtitle() {
return subtitle;
}
public String getDescription() {
return description;
}
public String getCategory() {
return category;
}
public String getStartTime() {
return startTime;
}
public String getEndTime() {
return endTime;
}
Channel.java
public class Channel implements ChannelInterface {
private String name;
private ArrayList<Program> programs;
public String getName() {
return name; //vergeet het return type niet
}
public ArrayList<Program> getPrograms() {
return programs;
}
public void addProgram(Program program) {
this.programs.add(program);
}
I get an error in the ChannelParser.java, because the Arraylist doesn't work, but I don't know how to resolve it.

Neither getting downstream message nor getting echo message using CCS

I downloaded the code from the below link for android which has option to send echo, broadcast as well as user notification message.
Link for Android
Then I tried to use many codes for server side without any success so I studied and wrote the below code for the server side which I have hosted on Tomcat Server and there is a servlet which activates the client.
public class CcsServlet extends HttpServlet
{
private static Logger logger = Logger.getLogger(CcsServlet.class.getName());
private static final String USERNAME = "855350893195" + "#gcm.googleapis.com";
private static final String PASSWORD = "AIzaSyA9DQTcggUtABVC9lnV_Xb5VEQ8iKBEaP4";//AIzaSyAxDKiYUkU8EvtOgaCeZMypVJpzcYgyjhw-server
public void init(ServletConfig config) throws ServletException
{
SmackCcsClient ccsManager = SmackCcsClient.getInstance();
try
{
ccsManager.connect(USERNAME,PASSWORD);
}
catch (Exception e)
{
logger.warning("Cannot connect to CCS server.");
e.printStackTrace();
}
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException{
}
}
Code for the SmackCcsClient
public class SmackCcsClient {
private static Logger log = LoggerFactory.getLogger(SmackCcsClient.class);
private static SmackCcsClient sInstance = null;
XMPPConnection connection;
ConnectionConfiguration config;
public SmackCcsClient() {
// Add GcmPacketExtension
ProviderManager.getInstance().addExtensionProvider(
GCMConstants.GCM_ELEMENT_NAME,
GCMConstants.GCM_NAMESPACE,
new PacketExtensionProvider() {
#Override
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
String json = parser.nextText();
GcmPacketExtension packet = new GcmPacketExtension(json);
return packet;
}
});
}
/**
* Returns a random message id to uniquely identify a message.
*
*/
public String getRandomMessageId() {
return UUID.randomUUID().toString();
}
/**
* Sends a downstream GCM message.
*/
public void send(String jsonRequest) {
Packet request = new GcmPacketExtension(jsonRequest).toPacket();
connection.sendPacket(request);
}
public static SmackCcsClient getInstance()
{
if (sInstance == null)
sInstance = new SmackCcsClient();
return sInstance;
}
/**
* Handles an upstream data message from a device application.
*
* <p>
* This sample echo server sends an echo message back to the device.
* Subclasses should override this method to process an upstream message.
*/
public void handleIncomingDataMessage(Map<String, Object> jsonObject) {
String from = jsonObject.get("from").toString();
// PackageName of the application that sent this message.
String category = jsonObject.get("category").toString();
// Use the packageName as the collapseKey in the echo packet
String collapseKey = "echo:CollapseKey";
#SuppressWarnings("unchecked")
Map<String, String> payload = (Map<String, String>) jsonObject.get("data");
payload.put("ECHO", "Application: " + category);
// Send an ECHO response back
String echo = createJsonMessage(from, getRandomMessageId(), payload, collapseKey, null, false);
send(echo);
}
/**
* Handles an ACK.
*
* <p>
* By default, it only logs a INFO message, but subclasses could override it
* to properly handle ACKS.
*/
public void handleAckReceipt(Map<String, Object> jsonObject) {
String messageId = jsonObject.get("message_id").toString();
String from = jsonObject.get("from").toString();
log.debug("handleAckReceipt from: {}, messageId: {}", from, messageId);
}
/**
* Handles a NACK.
*
* <p>
* By default, it only logs a INFO message, but subclasses could override it
* to properly handle NACKS.
*/
public void handleNackReceipt(Map<String, Object> jsonObject) {
String messageId = jsonObject.get("message_id").toString();
String from = jsonObject.get("from").toString();
log.debug("handleNackReceipt() from: {}, messageId: {}",from, messageId);
}
/**
* Creates a JSON encoded GCM message.
*
* #param to
* RegistrationId of the target device (Required).
* #param messageId
* Unique messageId for which CCS will send an "ack/nack"
* (Required).
* #param payload
* Message content intended for the application. (Optional).
* #param collapseKey
* GCM collapse_key parameter (Optional).
* #param timeToLive
* GCM time_to_live parameter (Optional).
* #param delayWhileIdle
* GCM delay_while_idle parameter (Optional).
* #return JSON encoded GCM message.
*/
public static String createJsonMessage(String to, String messageId,
Map<String, String> payload, String collapseKey, Long timeToLive,
Boolean delayWhileIdle) {
Map<String, Object> message = new HashMap<String, Object>();
message.put("to", to);
if (collapseKey != null) {
message.put("collapse_key", collapseKey);
}
if (timeToLive != null) {
message.put("time_to_live", timeToLive);
}
if (delayWhileIdle != null && delayWhileIdle) {
message.put("delay_while_idle", true);
}
message.put("message_id", messageId);
message.put("data", payload);
return JSONValue.toJSONString(message);
}
/**
* Creates a JSON encoded ACK message for an upstream message received from
* an application.
*
* #param to
* RegistrationId of the device who sent the upstream message.
* #param messageId
* messageId of the upstream message to be acknowledged to CCS.
* #return JSON encoded ack.
*/
public static String createJsonAck(String to, String messageId) {
Map<String, Object> message = new HashMap<String, Object>();
message.put("message_type", "ack");
message.put("to", to);
message.put("message_id", messageId);
return JSONValue.toJSONString(message);
}
/**
* Connects to GCM Cloud Connection Server using the supplied credentials.
*
* #param username
* GCM_SENDER_ID#gcm.googleapis.com
* #param password
* API Key
* #throws XMPPException
*/
public void connect(String username, String password) throws XMPPException {
config = new ConnectionConfiguration(GCMConstants.GCM_SERVER, GCMConstants.GCM_PORT);
config.setSecurityMode(SecurityMode.enabled);
config.setReconnectionAllowed(true);
config.setRosterLoadedAtLogin(false);
config.setSendPresence(false);
config.setSocketFactory(SSLSocketFactory.getDefault());
// NOTE: Set to true to launch a window with information about packets
// sent and received
config.setDebuggerEnabled(true);
// -Dsmack.debugEnabled=true
XMPPConnection.DEBUG_ENABLED = true;
connection = new XMPPConnection(config);
connection.connect();
//**code used to send downstream message**
String toRegId = "APA91bECAx_1rzceJbPwas5FyRGPmpYFvWSJ0hfUlT30DSsrsXmBC5W-VmYTI0p8Gg9VZh598iNBcVki-H1dloBnaETfvZlJUZskTxHKE7DoDAgapH_X_DJE3toyZwXS4SHIdt5lYLty6OU_tmAOTZN4n88jlmSaR2_MrNmY1HuAMlddMfqAr10";
String messageId = sInstance.getRandomMessageId();
Map<String, String> payload = new HashMap<String, String>();
payload.put("Hello", "World");
payload.put("CCS", "Dummy Message");
payload.put("EmbeddedMessageId", messageId);
String collapseKey = "sample";
Long timeToLive = 10000L;
Boolean delayWhileIdle = true;
sInstance.send(createJsonMessage(toRegId, messageId, payload,
collapseKey, timeToLive, delayWhileIdle));
connection.addConnectionListener(new ConnectionListener() {
#Override
public void reconnectionSuccessful() {
log.info("Reconnecting..");
}
#Override
public void reconnectionFailed(Exception e) {
log.info( "Reconnection failed.. ", e);
}
#Override
public void reconnectingIn(int seconds) {
log.info( "Reconnecting in %d secs", seconds);
}
#Override
public void connectionClosedOnError(Exception e) {
log.info( "Connection closed on error.");
}
#Override
public void connectionClosed() {
log.info("Connection closed.");
}
});
// Handle incoming packets
connection.addPacketListener(new PacketListener() {
#Override
public void processPacket(Packet packet) {
log.info( "Received: " + packet.toXML());
Message incomingMessage = (Message) packet;
GcmPacketExtension gcmPacket = (GcmPacketExtension) incomingMessage.getExtension(GCMConstants.GCM_NAMESPACE);
String json = gcmPacket.getJson();
try {
#SuppressWarnings("unchecked")
Map<String, Object> jsonObject = (Map<String, Object>) JSONValue
.parseWithException(json);
// present for "ack"/"nack", null otherwise
Object messageType = jsonObject.get("message_type");
if (messageType == null) {
// Normal upstream data message
handleIncomingDataMessage(jsonObject);
// Send ACK to CCS
String messageId = jsonObject.get("message_id")
.toString();
String from = jsonObject.get("from").toString();
String ack = createJsonAck(from, messageId);
send(ack);
} else if ("ack".equals(messageType.toString())) {
// Process Ack
handleAckReceipt(jsonObject);
} else if ("nack".equals(messageType.toString())) {
// Process Nack
handleNackReceipt(jsonObject);
} else {
// logger.log(Level.WARNING,
// "Unrecognized message type (%s)",
messageType.toString();
}
} catch (Exception e) {
// logger.log(Level.SEVERE, "Couldn't send echo.", e);
}
}
}, new PacketTypeFilter(Message.class));
// Log all outgoing packets
connection.addPacketWriterInterceptor(new PacketInterceptor() {
#Override
public void interceptPacket(Packet packet) {
log.info( "Sent: {0}", packet.toXML());
}
}, new PacketTypeFilter(Message.class));
connection.login(username, password);
}
}
Code for GcmPacketExtension
class GcmPacketExtension extends DefaultPacketExtension {
String json;
public GcmPacketExtension(String json) {
super(GCMConstants.GCM_ELEMENT_NAME, GCMConstants.GCM_NAMESPACE);
this.json = json;
}
public String getJson() {
return json;
}
#Override
public String toXML() {
return String.format("<%s xmlns=\"%s\">%s</%s>", GCMConstants.GCM_ELEMENT_NAME,
GCMConstants.GCM_NAMESPACE, json, GCMConstants.GCM_ELEMENT_NAME);
}
#SuppressWarnings("unused")
public Packet toPacket() {
return new Message() {
// Must override toXML() because it includes a <body>
#Override
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<message");
if (getXmlns() != null) {
buf.append(" xmlns=\"").append(getXmlns()).append("\"");
}
if (getDefaultLanguage() != null) {
buf.append(" xml:lang=\"").append(getDefaultLanguage())
.append("\"");
}
if (getPacketID() != null) {
buf.append(" id=\"").append(getPacketID()).append("\"");
}
if (getTo() != null) {
buf.append(" to=\"")
.append(StringUtils.escapeForXML(getTo()))
.append("\"");
}
if (getFrom() != null) {
buf.append(" from=\"")
.append(StringUtils.escapeForXML(getFrom()))
.append("\"");
}
buf.append(">");
buf.append(GcmPacketExtension.this.toXML());
buf.append("</message>");
return buf.toString();
}
};
}
}
Code for GcmConstants
public class GCMConstants {
public static final String GCM_SERVER = "gcm.googleapis.com";
public static final int GCM_PORT = 5235;
public static final String GCM_ELEMENT_NAME = "gcm";
public static final String GCM_NAMESPACE = "google:mobile:data";
}
Now when I try to send a downstream message using the code in connect that does not reach the device which device id I have given or Echo message from device also does not echoed by server.
Is it required to sign up thing for CCS required because I have already signed up, however did not get any response.
Second question is why neither of the communication is working.
Now I have cleared up all the issues and now my servlet is running and making a connection however it is returning "No Response from the server", which I am getting as exception while connecting.

Sending multipart POST data without external libraries

My Android app architecture is based on DefaultHttpClient. About 2 days ago, I header they're improving HttpURLConnection and I was about to change the whole architecture to work with it, but it seemed like too much code rewriting, so I sticked to DefaultHttpClient.
Now I'm having to upload a multipart entity and I have been reading about adding an external library called mime from Apache, which happens to be deprecated.
My question would be, is there a way to send multipart entity using the Android or Java SDK? Cause if there isn't then I suppose I'm gonna change it all to HttpURLConnection
You could try out some classes that I wrote for my projects. The multipart form class is a pretty trivial implementation, but it should be easily hackable to accommodate sending arrays of data or whatever you need.
/**
* Used to provide an interface for sending post data of various types.
*/
public interface PostData {
/**
* Add the specified field to the post data.
*
* #param name The name or title of the field.
* #param value The value of the field.
* #return This object (for streamed programming)
*/
public PostData addField(String name, String value);
/**
* End the data.
*/
public PostData end();
public String getContentType();
public String toString();
public int getLength();
}
/**
* Generate a multi-part form to post data.
*/
public static class MultiPartForm implements PostData {
private final static String boundary = "AaBbC0xQrpqqqqqqqq";
private StringBuilder sb = new StringBuilder();
public PostData addField(String name, String value) {
sb.append("--")
.append(boundary)
.append("\nContent-Disposition: form-data; name='")
.append(name)
.append("'\n\n")
.append(value)
.append("\n");
return this;
}
public PostData end() {
sb.append("--").append(boundary).append("--");
return this;
}
public final String getContentType() {
return "multipart/form-data;boundary=" + boundary;
}
public String toString() {
return sb.toString();
}
public int getLength() {
return sb.length();
}
}
/**
* Creates URL encoded data.
* Does not include the question mark at the beginning of the string.
*/
public static class UrlEncodedData implements PostData {
private StringBuilder sb = new StringBuilder();
public PostData addField(String name, String value) {
if (sb.length() > 0) {
sb.append("&");
}
try {
sb.append(URLEncoder.encode(name, "UTF-8"))
.append("=")
.append(URLEncoder.encode(value, "UTF-8"));
// Shouldn't ever happen.
} catch (java.io.UnsupportedEncodingException e) {}
return this;
}
public PostData end() {
return this;
}
public final String getContentType() {
return "application/x-www-form-urlencoded";
}
public String toString() {
return sb.toString();
}
public int getLength() {
return sb.length();
}
}
Along with these, I also created a method to make retrieving data more simple as well. I use HttpURLConnection with this method, but it should be pretty simple to get the gist of how to do the same thing with the DefaultHttpClient. Note that it is synchronous, so you will have to call it in another thread:
/**
* Loads a specified URL with the params incoded in the post.
*
* #throws Exception For numerous reasons.
* #param url The base URL to connect to.
* #param data A PostData object to fetch. Specifiy null for a GET request.
* #return The result.
*/
public static String loadUrl(final String url, final PostData data)
throws Exception {
HttpURLConnection urlConnection = null;
BufferedReader br = null;
final StringBuilder result = new StringBuilder();
try {
urlConnection = (HttpURLConnection)new URL(url).openConnection();
if (data != null) {
urlConnection.setRequestMethod("POST");;
urlConnection.setRequestProperty("Content-Type", data.getContentType());
urlConnection.setRequestProperty("Content-Length",
Integer.toString(data.getLength()));
urlConnection.setDoOutput(true);
DataOutputStream dos = new DataOutputStream(
urlConnection.getOutputStream());
dos.writeBytes(data.toString());
dos.flush();
dos.close();
urlConnection.connect();
}
br = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
result.append(line);
}
} finally {
try { urlConnection.disconnect(); } catch (Exception e) {}
try { br.close(); } catch (Exception e) {}
}
return result.toString();
}
Usage is quite trivial:
Utils.loadUrl("someApi.com/foobar/"
new Utils.MultiPartForm()
.addField("first_name", "John")
.addField("last_name", "Doe")
.end());

Categories