Images(base64) not uploading correctly - java

Unfortunately I'm facing some issues when I try to upload some images from an android device to a database.
The images are in a folder. This folder contains images as well as other stuff. I don't know the names of the images and I need to upload only the images(jpg). Before I upload the images I need to encode them with base64.
First I get the jpg files from the folder. Then I get the ID out of the image name. After that I encode it via base64:
Button upload = (Button) findViewById(R.id.upload);
upload.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
String path = Environment.getExternalStorageDirectory().getPath();
File dir = new File(path);
File[] files = dir.listFiles();
for (int i = 0; i < files.length; ++i) {
if (files[i].getName().endsWith(".jpg")) {
pics = new File(String.valueOf(files[i]));
id = String.valueOf(files[i]);
String sub = id.substring(id.lastIndexOf("/") + 1);
int index = sub.indexOf("_");
String book;
if (index >= 0) {
book = sub.substring(0, index);
ID = book;
Log.e("ID", ID);
}
Bitmap imagex = BitmapFactory.decodeFile(pics.getAbsolutePath());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
imagex.compress(Bitmap.CompressFormat.JPEG, 70, baos);
byte[] b = baos.toByteArray();
Image = Base64.encodeToString(b, Base64.DEFAULT);
try {
new HttpAsyncTask(ID,Image,Nummer).execute("https://....");
} catch (Exception e) {
Log.e("InputStream", e.getMessage());
}
Log.e("PICS", id);
}
}
}
});
public String POST(String url) {
InputStream inputStream;
try {
HttpClient httpclient = classxy.getNewHttpClient();
HttpPost httpPost = new HttpPost(url);
String json = "";
JSONObject jsonObject = new JSONObject();
jsonObject.put("bookId", ID);
jsonObject.put("imageString", Image);
jsonObject.put("imageNumber", Nummer);
json = jsonObject.toString();
StringEntity se = new StringEntity(json);
httpPost.setEntity(se);
httpPost.setHeader("Apikey", data);
httpPost.setHeader("Modul", "upload_image");
HttpResponse httpResponse = httpclient.execute(httpPost);
inputStream = httpResponse.getEntity().getContent();
if (inputStream != null)
result = classxy.convertInputStreamToString(inputStream);
else
result = "Fehler!";
} catch (Exception e) {
Log.e("InputStream", e.getLocalizedMessage());
}
int num = Integer.parseInt(Nummer);
num++;
Nummer = Integer.toString(num);
return result;
}
public class HttpAsyncTask extends AsyncTask<String, Void, String> {
private final Object ID, Image, Nummer;
public HttpAsyncTask(Object ID, Object Image, Object Nummer) {
this.ID = ID;
this.Image = Image;
this.Nummer = Nummer;
}
protected String doInBackground(String... urls) {
return POST(urls[0]);
}
protected void onPostExecute(String result) {
if (result.matches("(.*)false(.*)")) {
Toast.makeText(getApplicationContext(), "....", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "...", Toast.LENGTH_SHORT).show();
}
Log.e("RESPONSE", result);
}
}
It does encode the images via base64 and it does upload some of the images. Unfortunately it uploads only the first image or one image multiple times. It never uploads the correct amount of images in the correct order. I've been sitting on this problem for a while now and can't figure out what I'm doing wrong.
Can you tell me what I'm doing wrong?

Your program doesn't seem to be thread-safe at all.
Your fields ID, Image and Nummer are updated with every iteration of the for loop. Most likely the loop has already finished before POST runs for the first time. Your observation would support this assumption:
Unfortunately it uploads only the first image or one image multiple times.
You can observe this by logging every access to these fields. You'll find, that it's not alternating like you expect it to be.
Therefore you should implement everything without using these fields at all. Instead use local variables and pass these around. Using the Nummer field could be usefull if you want to use it for more than one upload. But it might be better to use an int directly:
upload.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
String ID = "", Image;
int Nummer = 0;
[...]
for (int i = 0; i < files.length; ++i) {
if (files[i].getName().endsWith(".jpg")) {
[...]
try {
new HttpAsyncTask(ID,Image,Integer.toString(Nummer++)).execute("https://....");
} catch (Exception e) {
Log.e("InputStream", e.getMessage());
}
Log.e("PICS", id);
}
}
}
});
public String POST(String url, String ID, String Image, String Nummer) {
InputStream inputStream;
try {
[...]
} catch (Exception e) {
Log.e("InputStream", e.getLocalizedMessage());
}
//int num = Integer.parseInt(Nummer);
//num++;
//Nummer = Integer.toString(num);
return result;
}
public class HttpAsyncTask extends AsyncTask<String, Void, String> {
private final String ID, Image, Nummer;
public HttpAsyncTask(String ID, String Image, String Nummer) {
this.ID = ID;
this.Image = Image;
this.Nummer = Nummer;
}
protected String doInBackground(String... urls) {
return POST(urls[0], ID, Image, Nummer);
}
protected void onPostExecute(String result) {
[...]
}
}

In My suggestion Dont call Asynctask directly from for loop because there are no any monitor on we can set for which image selected.
So Go through below steps:
1) In for loop get all images ID,Name and number and store it to ArrayList
2) Check ArrayList first is empty or not
if not then get first position ID, Image and number
call new HttpAsyncTask(ID,Image,Integer.toString(Nummer++)).execute("https://....");
3) In HttpAsyncTask onPostExecute(String result) method
first remove first position data
then create
for loop (i=0;i<ArrayList.Size();i++) {
ID=ArrayList first position data ID
Image=ArrayList first position data IMAGE
number=ArrayList first position data number
Call new HttpAsyncTask(ID,Image,Integer.toString(Nummer++)).execute("https://....");
}
So here first Image send by then after second then after third up to your list not empty and every time different image selected.
Thats it...

Related

How to Load an Array from .json file into App

My plan is do analyze an image via tensorflow and send the result to an app. Der result is written in a json file. The json file looks like that:
{"file": "image.jpg", "objects": [{"bbox": [177, 14, 508, 773], "label": "spanishguitar", "prob": 0.7284}]
my class in android studio is:
`
private class Downloadjson extends AsyncTask<Void, Void, Void> {
String name;
String label;
public Downloadjson(String name) {
this.name = name;
}
#Override
protected Void doInBackground(Void... params) {
String url = SERVER_ADRESS + name;
sleep(5000);
//animation start
for (int i = 0; i < 600; i++) {
HttpClient client = new DefaultHttpClient(getHttpRequestParams());
HttpGet getJson = new HttpGet(url);
try {
HttpResponse jsonResponse = client.execute(getJson);
if (200 == jsonResponse.getStatusLine().getStatusCode()) {
try {
InputStream inputStream = jsonResponse.getEntity().getContent();
String json = IOUtils.toString(inputStream);
Downloadjson downloadjson = new Gson().fromJson(json, Downloadjson.class);
String label = downloadjson.label;
TextView Result = (TextView) findViewById(R.id.textView);
Result.setText("Your instrument could be a " + downloadjson.label);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
//exucte
sleep(5000);
}
//stop animation
return null;
}
`
When I change "label" to "file" it works and the output is "image.jpg". But i need the "label" array with the output "spanishguitar". So, I think the problem is, that the object is not "label" but "objects" (in my json file). And label is an array? Do you know what I have to change to get the "label" ?
As I understand, you just need to properly traverse the json and assign value for label. Please try:
String label = downloadjson.objects[0].label;

Pull specific JSON objects from a specific array to put in another activity by an Intent in Android

I am creating a News Feed App, and I want to be able to pull information from a specific listing to a different layout that displays the title, source, image and content of the news listing. On the main page, the JSON will populate the list view with the title, source and image. I've sent an onItemClickListener, and when I click on each entry, I want it to open that entry in the new layout to display all the content. I have a class made just to pull the JSON info, so I'm not sure how to use that in the class with the onItemClick listener. I understand the putExtra, but I'm completely lost on the code to enter to transfer over what I need. Below is code from the page with the list, as well as the JsonQuery class. Thanks for any help!
TopHeadlinesFragment.java
public class TopHeadlinesFragment extends Fragment
implements LoaderManager.LoaderCallbacks<List<News>> {
public static final String NEWS_FEED_URL =
"https://newsapi.org/v2/top-headlines?country=us&apiKey=a3f791903c1a4163b223dd033563084b";
private static final int NEWS_LOADER_ID = 1;
private NewsAdapter mNewsAdapter;
private NewsAdapterListing mNewsAdapterListing;
public TopHeadlinesFragment(){
// Required empty public constructor
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.news_list, container, false);
mNewsAdapter = new NewsAdapter(getActivity(), new ArrayList<News>());
ListView listView = rootView.findViewById(R.id.list);
listView.setAdapter(mNewsAdapter);
final LoaderManager loaderManager = getLoaderManager();
loaderManager.initLoader(NEWS_LOADER_ID, null, this);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mNewsAdapterListing = new NewsAdapterListing(getActivity(), new ArrayList<News>());
News currentNews = mNewsAdapterListing.getItem(position);
Intent newsArticleDisplayIntent = new Intent(getActivity(), FullArticleListing.class);
startActivity(newsArticleDisplayIntent);
}
});
return rootView;
}
#Override
public Loader<List<News>> onCreateLoader(int id, Bundle args) {
return new NewsLoader(getActivity(), NEWS_FEED_URL);
}
#Override
public void onLoadFinished(Loader<List<News>> loader, List<News> data) {
mNewsAdapter.clear();
if (data != null && !data.isEmpty()){
mNewsAdapter.addAll(data);
}
}
#Override
public void onLoaderReset(Loader<List<News>> loader) {
mNewsAdapter.clear();
}
public static class NewsLoader extends AsyncTaskLoader<List<News>> {
private String[] mUrl;
public NewsLoader(Context context, String... url) {
super(context);
mUrl = url;
}
#Override
protected void onStartLoading() {
forceLoad();
}
#Override
public List<News> loadInBackground() {
if (mUrl.length < 1 || mUrl[0] == null) {
return null;
}
return JsonQueryUtils.fetchNewsData(mUrl[0]);
}
}
}
JsonQueryUtils.java
public class JsonQueryUtils {
/** Contains networking and JSON parsing code **/
private static final String LOG_TAG = "JsonQueryUtils";
private JsonQueryUtils(){
}
/** Helper method to fetch news data and call networking code within method **/
public static List<News> fetchNewsData(String requestUrl){
URL url = createUrl(requestUrl);
String jsonResponse = null;
try{
jsonResponse = makeHttpRequest(url);
} catch (IOException e){
Log.e(LOG_TAG, "Error closing input stream", e);
}
List<News> news = extractNews(jsonResponse);
Log.i(LOG_TAG, "fetchNewsData initialized");
return news;
}
private static List<News> extractNews (final String newsJSON) {
if (TextUtils.isEmpty(newsJSON)) {
return null;
}
List<News> news = new ArrayList<>();
try {
JSONObject jsonNewsObject = new JSONObject(newsJSON);
JSONArray newsArray = jsonNewsObject.getJSONArray("articles");
for (int i = 0; i < newsArray.length(); i++) {
JSONObject currentNews = newsArray.getJSONObject(i);
JSONObject source = currentNews.optJSONObject("source");
String imageUrl = currentNews.getString("urlToImage");
Bitmap newsImage = makeHttpRequest(imageUrl);
String title = currentNews.getString("title");
String sourceName = source.getString("name");
String content = currentNews.getString("content");
news.add(new News(newsImage, title, sourceName));
}
} catch (JSONException e) {
e.printStackTrace();
Log.e(LOG_TAG, "problem with parsing", e);
} catch (IOException e){
e.printStackTrace();
}
return news;
}
/**
* Make an HTTP request to the given imageURL and return a Bitmap as the response.
*/
private static Bitmap makeHttpRequest (String imageUrl) throws IOException {
Bitmap newsImage = null;
if (imageUrl == null){
return newsImage;
}
URL url = createUrl(imageUrl);
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoInput(true);
urlConnection.connect();
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
newsImage = BitmapFactory.decodeStream(inputStream);
}
} catch (IOException e) {
Log.e(LOG_TAG, "Error reading bitmap input stream");
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
inputStream.close();
}
}
return newsImage;
}
/**
* 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 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
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 reading input stream.", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
inputStream.close();
}
}
return jsonResponse;
}
/**
* Convert the {#link InputStream} into a String which contains the
* whole JSON response from the server.
*/
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();
}
/** Helper method to create {#link} URL object **/
private static final URL createUrl(String stringUrl) {
URL url = null;
try {
url = new URL(stringUrl);
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "createUrl: error", e);
}
return url;
}
}
I noticed you extracted the 'content' from JSON response but I don't see anywhere the variable 'content' getting used to construct the News object... Is there a reason why you don't include it to News object?
Regarding sending the News object to the next activity, there are few ways to achieve this.
Use Parcelable to send the News to your next activity/fragment. For more details, click here.
Install GSON library and simple convert your News object to Json String. Put that String in your Intent as an extra and launch the next Activity. Retrieve the data by calling new Gson().fromJson(). However, since your object has Bitmap field, this won't be a suitable approach. For more details, click here
This is what I would have done, if the API allows: Simply call the API request again for more details about the current feed. For example, you can execute another API request in your FullArticleActivity along with an ID that is associated with the selected feed. (i.e. User clicks a feed with an id #3 -> Pass the id(Integer) to the next Activity as an extra -> Retrieve the id from extras and make another API request using the id to retrieve full article details.) However, this is possible only when your API provides a GET method like this.
Create a Singleton and let it hold your object temporarily. Retrieve the object in the next activity by simple calling something like YourSingletonClass.getInstance().getNews().

Passing text and multiple images as an array using okhttp

I am using Okhttp lib to send data to server. I want to set text and images in RequestBody. For uploading multiple image to server using Okhttp i follow this link. I have implemented that type of code in my app in another activity class and its work fine. I have checked this question that how to pass array in RequestBody.
My arrayList format is like this
blockList
{
block0
{
description0 = First block
image0 = {image1, image2}
video0 = videolink
disp_order0 = 0
block0 = 0
}
block1
{
description1 = second block
image1 = {image1,image2,image2}
video1 = videolink
disp_order1 = 1
block1 = 1
}
.....
}
My Requirement :-
Now i want to send multiple images as an array in single parameter. When i send first block then parameter names are description0,image0[],video1,disp_order and block0 and image0[] will contain first block images as array and same for other.
API is working fine because when i test in postman then i receive the data in server side. You can see in below..
Here is my java function that set the data in RequestBody and make a call to send that data on sever.
ProgressDialog pd;
private OkHttpClient client;
private void saveCastBoxOnServer(String castBoxTitle, String selectedCastBoxId, String selectedCategoryId,
String userId, String action, ArrayList<CastBoxBlock> blockList)
{
try
{
client = new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.build();
ArrayList<CastBoxBlock> blockArrayList = blockList;
int blockSize = blockArrayList.size();
MultipartBody.Builder multipartBuilderNew = new MultipartBody.Builder().setType(MultipartBody.FORM);
for (int i = 0; i < blockSize; i++)
{
String description = blockArrayList.get(i).getBlockDescription();
String descriptionField = "description"+i;
multipartBuilderNew.addFormDataPart(descriptionField, description);
/**This is used for distribution of images and videos. After that set that
* Images and video in multipartBuilder.
**/
CastBoxBlock model = blockArrayList.get(i);
ArrayList<SelectedMediaModel> mediaModels = model.getSelectedMediaModelArrayList();
int mediaModelsSize = mediaModels.size();
String passingVideoUri = "";
String videoUri = "";
for (int j = 0; j < mediaModelsSize; j++)
{
String mediaType = mediaModels.get(j).getMediaType();
if (mediaType.equals(StringKeyConstant.mediaVideo))
{
videoUri = mediaModels.get(j).getMediaPath();
if (passingVideoUri.trim().length()==0){
passingVideoUri = videoUri;
}else{
passingVideoUri = passingVideoUri + "," + videoUri;
}
}
else if (mediaType.equals(StringKeyConstant.mediaImage))
{
String imagePath = mediaModels.get(j).getMediaPath();
File sourceFile = new File(imagePath);
/**Changes whether JPEG or PNG**/
final MediaType MEDIA_TYPE = MediaType.parse(
constant.getFileExt(imagePath).endsWith("png") ? "image/png" : "image/jpeg");
String imageName = System.currentTimeMillis() + j + "_block_img.jpg";
String imageField = "image"+i+"["+j+"]";
multipartBuilderNew.addFormDataPart(imageField,imageName,
RequestBody.create(MEDIA_TYPE, sourceFile));
}
}
/**This is used to set the {#videoUri} block of videos and send to sever**/
String videoField = "video"+i;
multipartBuilderNew.addFormDataPart(videoField, passingVideoUri);
/**This will set the {#display_order} in multipartBuilder**/
String displayOrderField = "disp_order"+i;
String displayOrder = blockArrayList.get(i).getBlockIndex();
multipartBuilderNew.addFormDataPart(displayOrderField, displayOrder);
/**This will set the {#block} value in multipartBuilder**/
String blockField = "block"+i;
String block = ""+i;
multipartBuilderNew.addFormDataPart(blockField, block);
}
pd = new ProgressDialog(activity);
pd.setCancelable(false);
pd.setMessage(getResources().getString(R.string.please_wait));
pd.show();
RequestBody formBody = multipartBuilderNew
.addFormDataPart("cast_title", castBoxTitle)
.addFormDataPart("user_id", userId)
.addFormDataPart("cast_box", selectedCastBoxId)
.addFormDataPart("category", selectedCategoryId)
.addFormDataPart("action", action)
.build();
Request request = new Request.Builder()
.url(ApiUtils.ADD_FETCH_USER_CAST)
.post(formBody)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, "Get Api credential fail."+call.toString());
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException
{
try
{
if (pd != null){
pd.cancel();
pd.dismiss();
pd = null;
}
String castSavedResponse = response.body().string();
Log.i(TAG, "castSavedResponse = " + castSavedResponse);
}
catch (Exception e){
Log.e(TAG, "***Error : onResponse() method");
e.printStackTrace();
}
}
});
}
catch (Exception e){
Log.e(TAG, "***Error : saveCastBoxOnServer()");
e.printStackTrace();
}
}
Thanks in advance. If any one will help it would be very appreciate.
When i check your code then i note one things. I am no sure but i think you change your code on image[] place. you can just change your code as below. I hope this will help you and you got the solution.
Use this code
String imageField = "image"+i+"[]";
Instead of
String imageField = "image"+i+"["+j+"]";
when i passed simple images as an array in Okhttp then i do code as above. For uploading multiple images on server using Okhttp, i also follow this link as you follow.

Display And Use Information From A DownloadTask In Android Studio

First time using Android Studio in any large capacity. Using the code from here: https://stackoverflow.com/a/30937657/5919360, I was able to successfully pull the information I wanted from the URL, but I can't figure out how use it.
Note: I know IMEI is not a good way to check for user registration and will be changing it later.
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
// Create instance and populates based on content view ID
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
// store IMEI
String imei = tm.getDeviceId();
// store phone
String phone = tm.getLine1Number();
// Display IMEI - Testing Purposes Only
TextView imeiText = (TextView) findViewById(R.id.imeiDisplay);
imeiText.setText("IMEI:" + imei);
// Display phone number - Testing Purposes Only
TextView phoneText = (TextView) findViewById(R.id.phoneDisplay);
phoneText.setText("Phone:" + phone);
new DownloadTask().execute("http://www.url.com/mobileAPI.php?action=retrieve_user_info&IMEI="+imei);
}
private class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
try {
return downloadContent(params[0]);
} catch (IOException e) {
return "Unable to retrieve data. URL may be invalid.";
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
}
}
private String downloadContent(String myurl) throws IOException {
InputStream is = null;
int length = 500;
try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
int response = conn.getResponseCode();
Log.d(TAG, "The response is: " + response);
is = conn.getInputStream();
// Convert the InputStream into a string
String contentAsString = convertInputStreamToString(is, length);
return contentAsString;
} finally {
if (is != null) {
is.close();
}
}
}
public String convertInputStreamToString(InputStream stream, int length) throws IOException, UnsupportedEncodingException {
Reader reader = null;
reader = new InputStreamReader(stream, "UTF-8");
char[] buffer = new char[length];
reader.read(buffer);
return new String(buffer);
}
}
This code returns an xml file, as a toast:
<?xml version="1.0" encoding="ISO-8859-1"?>
<mobile_user_info>
<rec>45</rec>
<IMEI>9900990099009</IMEI>
<fname>First</fname>
<lname>Last</lname>
<instance>instance1</instance>
<registered>N</registered>
</mobile_user_info>
I'm hoping someone can point me in the right direction for separating each line and using it independently. For example, if the Registered line comes back as N, a message is displayed like, 'You are not registered. Please contact administrator.'
Actually you should use an XML parser to parse the server's response. But if responses are always as simple as your example, you can use a regular expression to extract out the IMEI field.
String contentAsString = ...
Pattern pattern = Pattern.compile("<IMEI>(\d*)</IMEI>");
Matcher matcher = pattern.matcher(contentAsString);
if (matcher.find()) {
String imei = matcher.group(1);
}

Return data from AsyncTask class

How do I get the data from my AsyncTask? My MainActivity is calling the DataCall.getJSON function that triggers the AsyncTask but I am not sure how to get the data back to the original Activity.
MainActivity with call to DataCall that should return a string and save it in state_data
String state_data = DataCall.getJSON(spinnerURL,spinnerContentType);
DataCall:
public class DataCall extends Activity {
private static final String TAG = "MyApp";
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
protected void onPostExecute(String result) {
//THIS IS WHERE I NEED TO RETURN MY DATA TO THE MAIN ACTIVITY. (I am guessing)
}
}
public void getJSON(String myUrlString, String contentType) {
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] { "http://www.mywebsite.com/" + myUrlString });
}
}
modify your AsyncTask as below:
public class GetData extends AsyncTask<String, Void, String>
{
DataDownloadListener dataDownloadListener;
public GetData()
{
//Constructor may be parametric
}
public void setDataDownloadListener(DataDownloadListener dataDownloadListener) {
this.dataDownloadListener = dataDownloadListener;
}
#Override
protected Object doInBackground(Object... param)
{
// do your task...
return null;
}
#Override
protected void onPostExecute(Object results)
{
if(results != null)
{
dataDownloadListener.dataDownloadedSuccessfully(results);
}
else
dataDownloadListener.dataDownloadFailed();
}
public static interface DataDownloadListener {
void dataDownloadedSuccessfully(Object data);
void dataDownloadFailed();
}
}
and use it in your Activity
GetData getdata = new GetData();
getdata.setDataDownloadListener(new DataDownloadListener()
{
#SuppressWarnings("unchecked")
#Override
public void dataDownloadedSuccessfully(Object data) {
// handler result
}
#Override
public void dataDownloadFailed() {
// handler failure (e.g network not available etc.)
}
});
getdata.execute("");
NOTE: For the people who are reading this.
Please consider this post for the best and perhaps right implementation.
The key for me was to create a class called URLWithParams or something because AsyncTask will allow only 1 type to be sent IN, and I needed both the URL and the params for the HTTP request.
public class URLWithParams {
public String url;
public List<NameValuePair> nameValuePairs;
public URLWithParams()
{
nameValuePairs = new ArrayList<NameValuePair>();
}
}
and then I send it to a JSONClient:
public class JSONClient extends AsyncTask<URLWithParams, Void, String> {
private final static String TAG = "JSONClient";
ProgressDialog progressDialog ;
GetJSONListener getJSONListener;
public JSONClient(GetJSONListener listener){
this.getJSONListener = listener;
}
#Override
protected String doInBackground(URLWithParams... urls) {
return connect(urls[0].url, urls[0].nameValuePairs);
}
public static String connect(String url, List<NameValuePair> pairs)
{
HttpClient httpclient = new DefaultHttpClient();
if(url == null)
{
Log.d(TAG, "want to connect, but url is null");
}
else
{
Log.d(TAG, "starting connect with url " + url);
}
if(pairs == null)
{
Log.d(TAG, "want to connect, though pairs is null");
}
else
{
Log.d(TAG, "starting connect with this many pairs: " + pairs.size());
for(NameValuePair dog : pairs)
{
Log.d(TAG, "example: " + dog.toString());
}
}
// Execute the request
HttpResponse response;
try {
// Prepare a request object
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(pairs));
response = httpclient.execute(httpPost);
// Examine the response status
Log.i(TAG,response.getStatusLine().toString());
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String json = reader.readLine();
return json;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String json ) {
getJSONListener.onRemoteCallComplete(json);
}
public interface GetJSONListener {
public void onRemoteCallComplete(String jsonFromNet);
}
}
Then call it from my main class like this
public class BookCatalog implements GetJSONListener {
private final String TAG = this.getClass().getSimpleName();
private String catalog_url = "URL";
private void getCatalogFromServer() {
URLWithParams mURLWithParams = new URLWithParams();
mURLWithParams.url = catalog_url;
try {
JSONClient asyncPoster = new JSONClient(this);
asyncPoster.execute(mURLWithParams);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onRemoteCallComplete(String jsonBookCatalogList) {
Log.d(TAG, "received json catalog:");
Log.d(TAG, jsonBookCatalogList);
JSONObject bookCatalogResult;
try {
bookCatalogResult = (JSONObject) new JSONTokener(jsonBookCatalogList).nextValue();
JSONArray books = bookCatalogResult.getJSONArray("books");
if(books != null) {
ArrayList<String> newBookOrdering = new ArrayList<String>();
int num_books = books.length();
BookCatalogEntry temp;
DebugLog.d(TAG, "apparently we found " + Integer.toString(num_books) + " books.");
for(int book_id = 0; book_id < num_books; book_id++) {
JSONObject book = books.getJSONObject(book_id);
String title = book.getString("title");
int version = book.getInt("price");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Although i disagree creating a new activity for that simple task there is
startActivityForResult()
to get data from another activity.
Check this. You can store your data to the Intent's extras. But still if you have a large amount of data you better off write it to a file get the result from the other activity that is done downloading and then read the file.
Serialize it and then read it. The only way I'm aware of.
Some options:
a) Make your bean implement Serializable interface, you can then pass your bean through Intent.
b) Implement Application interface (you need to make an entry in manifest), Have setter\getter method in your Application class. You can set your bean in Application from AsyncTask and later retrieve from Activity.
Sorry for answering so late, i think by this time you might have solved this problem. when i was searching for something else, i came across your question. I'm pasting a link here which might of some help for others.

Categories