I'm trying to upload multiple images to a PHP server along with a few other parameters (strings), using the POST method. I'm using Multipart method. I added 4 libraries prescribed in various solutions (apachemime, httpclient, httpmime, httpcore), but my SDK doesn't recognise MultipartEntity, displaying the error: 'cannot be resolved to a type'. I've also tried MultipartEntityBuilder, but even that's showing the same error. I basically want to upload a Bitmap Arraylist to the server & show a progress bar simultaneously.
You should post some code with the issue so we can take a look and help you.
But if you want to try something a little bit simple you can use this library, AsyncHttpClient: http://loopj.com/android-async-http/
Using this library you could post multiple files like this:
private static AsyncHttpClient clientHttp = new AsyncHttpClient();
...
RequestParams params = new RequestParams();
final String TAG_FILE = "archivo1";
final String TAG_FILE_1 = "archivo2";
final String TAG_FILE_2 = "archivo3";
final String PATH_FILE_1 = ApplicationContext.getInstance().getFilesDir().getPath() + "/" + "file1.jpg";
final String PATH_FILE_2 = ApplicationContext.getInstance().getFilesDir().getPath() + "/" + "file2.jpg";
final String PATH_FILE_3 = ApplicationContext.getInstance().getFilesDir().getPath() + "/" + "file3.jpg";
try {
params.put(TAG_FILE, PATH_FILE_1);
params.put(TAG_FILE_1, PATH_FILE_2);
params.put(TAG_FILE_2, PATH_FILE_3);
params.put(TAG_PARAM, "SOME TEXT");
}
catch(FileNotFoundException e) {
//Manage your exception
}
final int DEFAULT_TIMEOUT = 30 * 1000;
clientHttp.setTimeout(DEFAULT_TIMEOUT);
clientHttp.post("http://somereceiver.php", params, new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONObject response) {
//Do your code on success
}
#Override
public void onStart() {
// Show your progress bar
}
#Override
public void onFinish() {
// Hide your progress bar
super.onFinish();
if(PATH_FILE_1 != null) {
File tem = new File(PATH_FILE_1);
if(tem.exists()) tem.delete();
}
if(PATH_FILE_2 != null) {
File tem = new File(PATH_FILE_2);
if(tem.exists()) tem.delete();
}
if(PATH_FILE_3 != null) {
File tem = new File(PATH_FILE_3);
if(tem.exists()) tem.delete();
}
}
});
You could also use the generic response type if you dont need json, so you get a string.
Hope this helps.
Related
Aim
In a fragment, I have a search bar which looks for online news about what the user typed. I would want to display these news (title + description + date of publication + ... etc.) in the GUI, as vertical blocks.
Implementation
Explanations
In the fragment, within the search event handling, I instanciated an asynchronous task and execute it with the good URL REST API I use to do the search.
In the asynchronous task, I make use of this REST API (thanks to the URL and some required parameters as an authorization key, etc.). When my asynchronous task gets answered, it must update the fragment's GUI (i.e.: it must vertically stack GUI blocks containing the titles, descriptions, etc. of the got news).
Sources
You will find sources in the last part of this question.
My question
In the asynchronous task (more precisely: in its function that is executed after having got the answer), I don't know how to get the calling fragment. How to do this?
Sources
Fragment part
private void getAndDisplayNewsForThisKeywords(CharSequence keywords) {
keywords = Normalizer.normalize(keywords, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "");
new NetworkUseWorldNews().execute("https://api.currentsapi.services/v1/search?keyword=" + keywords + "&language=en&country=US");
}
Asynchronous task part
public class NetworkUseWorldNews extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String[] urls) {
StringBuilder string_builder = new StringBuilder();
try {
URL url = new URL(urls[0]);
HttpsURLConnection https_url_connection = (HttpsURLConnection) url.openConnection();
https_url
_connection.setRequestMethod("GET");
https_url_connection.setDoOutput(false);
https_url_connection.setUseCaches(false);
https_url_connection.addRequestProperty("Authorization", "XXX");
InputStream input_stream = https_url_connection.getInputStream();
BufferedReader buffered_reader = new BufferedReader(new InputStreamReader(input_stream));
String line;
while((line = buffered_reader.readLine()) != null) {
string_builder.append(line);
}
buffered_reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return string_builder.toString();
}
#Override
protected void onPostExecute(String result) {
try {
JSONObject news_response_http_call = new JSONObject(result);
switch(news_response_http_call.getString("status")) {
case "ok":
JSONArray news = news_response_http_call.getJSONArray("news");
for(int i = 0; i < news.length(); i++) {
JSONObject a_news = news.getJSONObject(i);
String title = a_news.getString("title");
String description = a_news.getString("description");
String date_of_publication = a_news.getString("published");
String url = a_news.getString("url");
String image = a_news.getString("image");
System.out.println(title + ": " + date_of_publication + "\n" + image + "\n" + url + "\n" + description);
WorldNewsFragment world_news_fragment = ...;
}
break;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
If I am right, you want to update View of your caller Fragment. if FragmentA called service then FragmentA should be update.
However the approach you are asking is wrong. Instead of getting caller Fragment in your AsyncTask response. You should do it with Callback.
So now you will need to pass callback in AsyncTask. So instead of posting full code, here are already answers with this problem.
Finally your calling syntax will look like.
NetworkUseWorldNews task = new NetworkUseWorldNews(new OnResponseListener() {
#Override
public void onResponse(String result) {
// Either get raw response, or get response model
}
});
task.execute();
Actually I am still very unclear about your question. Let me know in comments if you have more queries.
Must checkout
Retrofit or Volley for calling Rest APIs
Gson for parsing JSON response automatically to models
I need a working example for a custom API for Microsoft Azure App Service.
I could not get any useful or working information/examples for that, or they just show each time different approaches which are outdated?!?!
For now I have a working table controller which gets information from database and returns it back to my Android client. Now I need to define a custom API Controller to get a string back. In the examples they are all sending an object to the service in order to get an object back. I do not want to send anything to the API, just retrieve some information back from a GET Request.
Regards
// EDIT - Added / edited client / server code to Post a String.
You can use the following code to do a GET request on the auto generated API controller Visual Studio creates (ValuesController).
private void getStringFromAzure() throws MalformedURLException {
// Create the MobileService Client object and set your backend URL
String yourURL = "https://yourApp.azurewebsites.net/";
MobileServiceClient mClient = new MobileServiceClient(yourURL, this);
// Your query pointing to yourURL/api/values
ListenableFuture<JsonElement> query = mClient.invokeApi("values", null, GetMethod, null);
// Callback method
Futures.addCallback(query, new FutureCallback<JsonElement>() {
#Override
public void onSuccess(JsonElement jsonElement) {
// You are expecting a String you can just output the result.
final String result = jsonElement.toString();
// Since you are on a async task, you need to show the result on the UI thread
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(mContext, result, Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onFailure(Throwable throwable) {
Log.d(TAG, "onFailure: " + throwable.getMessage());
}
});
}
public void sendString(final String someString) throws MalformedURLException {
// Your query pointing to /api/values/{String}
ListenableFuture<JsonElement> query = mClient.invokeApi("values/" + someString, null, PostMethod, null);
// Callback method
Futures.addCallback(query, new FutureCallback<JsonElement>() {
#Override
public void onSuccess(JsonElement jsonElement) {
// You are expecting a String you can just output the result.
final String result = jsonElement.toString();
}
#Override
public void onFailure(Throwable throwable) { }
});
}
The backend API: (ValuesController)
{
// Use the MobileAppController attribute for each ApiController you want to use
// from your mobile clients
[MobileAppController]
public class ValuesController : ApiController
{
// GET api/values
public string Get()
{
return "Hello World!";
}
// POST api/values/inputString
public string Post(string inputString)
{
return inputString;
}
}
}
You can also send parameters along in the following way:
List<Pair<String, String>> parameters = new ArrayList<>();
parameters.add(new Pair<>("name", "John"));
parameters.add(new Pair<>("password", "fourwordsalluppercase"));
ListenableFuture<JsonElement> query = client.invokeApi("yourAPI", PostMethod, parameters);
Or as json in the body:
JsonObject body = new JsonObject();
body.addProperty("currentPassword", currentPassword);
body.addProperty("password", password);
body.addProperty("confirmPassword", confirmPassword);
ListenableFuture<JsonElement> query = mClient.invokeApi("yourAPI", body, PostMethod, null);
Based on my understanding, I think there are two parts in your question which include as below. And I think you can separately refer to two sections to get the answers and write your own example.
How to define a custom API on Azure Mobile App to retrieve data from database? Please refer to the section Custom APIs to know how to do with Azure Mobile App backend.
How to call a custom API from Android App? Please refer to the section How to: Call a custom API to know how to do with Android SDK.
This is the first time ever I am using multi part request to upload data on the server.I am using ion for service hit can you please let me know how can I post my data on the server?
This is my request parameter
jSON Request:
{s_id
note_name
file_name
tag_name
set_date
mark_as_done
clear_reminder
Description
media_name1
media_name2
media_name3
Count = 3 }
Along with it, I have to upload file media1, media2, media2 on same api**. Any help would be greatly appreciated.Thanks
You can't do a JSON body and a Multipart body in one HTTP request.
you can send your json as a parameter :)
// first create your json object
JsonObject object = new JsonObject();
object.addProperty("note_name", "your value goes here");
object.addProperty("description", "your description goes here");
// add other stuffs here
//create list of files to upload
List<Part> files = new ArrayList<>();
for (int i = 1; i <= 3; i++) {
files.add(new FilePart("file" + i, new File("path of file like: storage/image/....")));
}
Ion.with(context)
.load("POST","http://example.com")
.uploadProgress(new ProgressCallback() {
#Override
public void onProgress(long downloaded, long total) {
int percent = (int) (downloaded * 100 / total);
// update your progressbar with this percent if needed
}
})
.addMultipartParts(files)
.setMultipartParameter("json", object.toString()) // your json is here
.asString()
.setCallback(new FutureCallback<String>() {
#Override
public void onCompleted(Exception e, String result) {
if (e != null) {
// error: log the message here
return;
}
if (result != null) {
// result is the response of your server
}
}
});
Hope this help you :)
I'm using Dropbox Android SDK for getting photos and show it into a GridView.
Currently, I'm using Picasso for adapter with another images resources like GPhotos, Facebook... too.
How can I get downloadable link from Dropbox's file? Or How to use Picasso load Dropbox's image?
This is the way I get the Dropbox image:
List<Entry> listEntry = mApi.search("/photos", ".jpg", 0, false);
int i = 0;
for (Entry entry : listEntry) {
if (this.isRemoving()) { // Check if fragment is being removed
return;
}
if (!entry.isDir) { // Check if this entry is dir or file
i++;
Log.e(TAG, entry + " --- " + entry.fileName() + " --- "
+ entry.parentPath() + " --- " + entry.modified);
final DropboxLink shareLink = mApi.share(entry.parentPath()
+ entry.fileName());
url = shareLink.url;
Log.v(TAG, "shareLink: " + shareLink.url);
// The file name I get is ImageName.JPG and path is /Photos
// With share() the url I get looks like https://db.tt/xxxxxxxx
}
}
I can't offer insight about using Picasso, but if you can accept the file data directly, using getFile or getThumbnail instead of share would be better.
If you do need a URL that Picasso can directly download from, you should use the media method instead.
Thanks #Greg for suggestion, i have a little notice for using Picasso with Dropbox SDK.
When use media i have to use option TRUE in SSL for success loading image from Picasso, if FALSE Picasso cannot load links.
There is a sample from dropbox about this, try to check this link dropbox sample
there is 2 files that you need to see PicassoClient.java And FileThumbnailRequestHandler.java
here's the code :
PicassoClient Class :
public class PicassoClient {
private static Picasso sPicasso;
public static void init(Context context, DbxClientV2 dbxClient) {
// Configure picasso to know about special thumbnail requests
sPicasso = new Picasso.Builder(context)
.downloader(new OkHttpDownloader(context))
.addRequestHandler(new FileThumbnailRequestHandler(dbxClient))
.build();
}
public static Picasso getPicasso() {
return sPicasso;
}
}
FileThumbnailRequestHandler class :
public class FileThumbnailRequestHandler extends RequestHandler {
private static final String SCHEME = "dropbox";
private static final String HOST = "dropbox";
private final DbxClientV2 mDbxClient;
public FileThumbnailRequestHandler(DbxClientV2 dbxClient) {
mDbxClient = dbxClient;
}
/**
* Builds a {#link Uri} for a Dropbox file thumbnail suitable for handling by this handler
*/
public static Uri buildPicassoUri(FileMetadata file) {
return new Uri.Builder()
.scheme(SCHEME)
.authority(HOST)
.path(file.getPathLower()).build();
}
#Override
public boolean canHandleRequest(Request data) {
return SCHEME.equals(data.uri.getScheme()) && HOST.equals(data.uri.getHost());
}
#Override
public Result load(Request request, int networkPolicy) throws IOException {
try {
DbxDownloader<FileMetadata> downloader =
mDbxClient.files().getThumbnailBuilder(request.uri.getPath())
.withFormat(ThumbnailFormat.JPEG)
.withSize(ThumbnailSize.W1024H768)
.start();
return new Result(downloader.getInputStream(), Picasso.LoadedFrom.NETWORK);
} catch (DbxException e) {
throw new IOException(e);
}
}
}
You just need to import those 2 classes that i mentioned above then get the sPicasso object then you're ready to use it . :)
Alrighty, so I understand that this general question has been asked numerous times here, but I have yet to find an answer that makes sense to me. Almost every answer I've seen just says some blurb like, "hey, just throw this in your method and you're good", but I'm not seeing full examples, and what I've tried is not working either.
Here's the error I receive:
[mono] android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
So, simply put, I have an activity that grabs some information from a web service and then throws the web service results into a couple of TextViews. Could someone please help me figure out where and how I need to use the RunOnUiThread()? Here's the code:
using Android.App;
using Android.OS;
using System;
using System.Web;
using System.Net;
using System.IO;
using Newtonsoft.Json;
using Android.Widget;
namespace DispatchIntranet
{
[Activity (Label = "#string/Summary")]
public class SummaryActivity : Activity
{
private static readonly Log LOG = new Log(typeof(SummaryActivity));
private TextView summaryTotalRegularLabel;
private TextView summaryTotalRollover;
private TextView summaryScheduledLabel;
private TextView summaryRemainingRegular;
private string url;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// SET THE LAYOUT TO BE THE SUMMARY LAYOUT
SetContentView(Resource.Layout.Summary);
// INITIALIZE CLASS MEMBERS
init();
if (LOG.isInfoEnabled())
{
LOG.info("Making call to rest endpoint . . .");
if (LOG.isDebugEnabled())
{
LOG.debug("url: " + this.url);
}
}
try
{
// BUILD REQUEST FROM URL
HttpWebRequest httpReq = (HttpWebRequest)HttpWebRequest.Create(new Uri(this.url));
// SET METHOD TO 'GET'
httpReq.Method = GetString(Resource.String.web_service_method_get);
// ASK FOR JSON RESPONSE
httpReq.Accept = GetString(Resource.String.web_service_method_accept);
// INVOKE ASYNCHRONOUS WEB SERVICE
httpReq.BeginGetResponse((ar) => {
HttpWebRequest request = (HttpWebRequest)ar.AsyncState;
using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse (ar))
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
// PUT RESPONSE INTO STRING
string content = reader.ReadToEnd();
// CONVERT STRING TO DYNAMIC JSON OBJECT
var json = JsonConvert.DeserializeObject<dynamic>(content);
if (LOG.isDebugEnabled())
{
LOG.debug("content: " + content);
LOG.debug("json: " + json);
LOG.debug("TOTAL_REGULAR_PTO_HOURS: " + json.d[0].TOTAL_REGULAR_PTO_HOURS);
}
// ** THIS IS WHAT WILL NOT WORK **
this.summaryTotalRegularLabel.Text = json.d[0].TOTAL_REGULAR_PTO_HOURS;
this.summaryTotalRollover.Text = json.d[0].TOTAL_ROLLOVER_PTO_HOURS;
this.summaryScheduledLabel.Text = json.d[0].TOTAL_USED_PTO_HOURS;
this.summaryRemainingRegular.Text = json.d[0].TOTAL_REMAINING_PTO_HOURS;
}
}
}, httpReq);
}
catch (Exception e)
{
LOG.error("An exception occurred while attempting to call REST web service!", e);
}
}
private void init()
{
// GET GUID FROM PREVIOUS INTENT AND DETERMINE CURRENT YEAR
string guid = Intent.GetStringExtra("guid");
int year = DateTime.Now.Year;
// BUILD URL
this.url = GetString(Resource.String.web_service_url)
+ GetString(Resource.String.ws_get_pto_summary)
+ "?" + "guid='" + HttpUtility.UrlEncode(guid) + "'"
+ "&" + "year=" + HttpUtility.UrlEncode(year.ToString());
// GET THE SUMMARY LABELS
this.summaryTotalRegularLabel = FindViewById<TextView>(Resource.Id.SummaryTotalRegular);
this.summaryTotalRollover = FindViewById<TextView>(Resource.Id.summaryTotalRollover);
this.summaryScheduledLabel = FindViewById<TextView>(Resource.Id.summaryScheduledLabel);
this.summaryRemainingRegular = FindViewById<TextView>(Resource.Id.SummaryRemainingRegular);
}
}
}
When you make a web service call, HttpWebRequest creates a new thread to run the operation on. This is done to keep your user interface from locking up or skip frames. Once your web service call is complete, you need to go back to the UI Thread to update the UI components that live on that thread. You can do that a couple of different ways.
First, you can wrap your code in an anonymous function call like so:
RunOnUiThread(()=>{
this.summaryTotalRegularLabel.Text = json.d[0].TOTAL_REGULAR_PTO_HOURS;
this.summaryTotalRollover.Text = json.d[0].TOTAL_ROLLOVER_PTO_HOURS;
this.summaryScheduledLabel.Text = json.d[0].TOTAL_USED_PTO_HOURS;
this.summaryRemainingRegular.Text = json.d[0].TOTAL_REMAINING_PTO_HOURS;
});
Or you can call a function via RunOnUiThread (jsonPayload is a field on the class):
jsonPayload = json;
RunOnUiThread(UpdateTextViews);
...
void UpdateTextViews()
{
this.summaryTotalRegularLabel.Text = jsonPayload.d[0].TOTAL_REGULAR_PTO_HOURS;
this.summaryTotalRollover.Text = jsonPayload.d[0].TOTAL_ROLLOVER_PTO_HOURS;
this.summaryScheduledLabel.Text = jsonPayload.d[0].TOTAL_USED_PTO_HOURS;
this.summaryRemainingRegular.Text = jsonPayload.d[0].TOTAL_REMAINING_PTO_HOURS;
}