Here is my code:
private void upload() {
Task task = new Task();
task.execute();
}
class Task extends AsyncTask<String, String, String> {
#SuppressLint("NewApi")
#Override
protected String doInBackground(String... params) {
try {
URL mUrl = new URL(HttpUrls.getUrl() + HttpUrls.UPLOAD_IMAGE);
SSLContext sslContext = Global.getSSLContext(AppConfig.getApplicationContext());
HttpsURLConnection conn = (HttpsURLConnection) mUrl
.openConnection(); conn.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
conn.setSSLSocketFactory(sslContext.getSocketFactory());
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty(Constants.Field.USER_UUID, mProductUuid);
conn.setRequestProperty(Constants.Field.IMG_TYPE, IMGType.PDT_IMG.name());
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
OutputStream output = conn.getOutputStream();
if (StringUtils.isEmpty2(mImgPath)) {
output.write(begin(System.currentTimeMillis() + ".jpg"));
} else {
output.write(begin(mImgPath));
}
if (mUri != null) {
Bitmap bitmap = ImageFactory.getBitmapFormUri(GalleryActivity.this, mUri, true);
output.write(ImageFactory.bitmapToByteAAA(bitmap));
try {
bitmap.recycle();
} catch (Exception e) {
}finally{
if(bitmap!=null && !bitmap.isRecycled()){
bitmap.recycle();
bitmap = null;
}
}
} else {
output.write(ImageFactory.bitmapToByteBBB(mBitmap));
}
output.write(end());
output.flush();
output.close();
return IOUtils.toString(conn.getInputStream());
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
I use the self defined certificate in my server, and I have load the trust.bks in Gloabal.getSSLContext(Application.getApplicationContext()) ,and I call the upload() method every time I click the upload button.
But it is weird that when I click the upload button for the first time, I get the error "hostname is not verified", which means conn.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); in my code didn't work, and when I click the upload button for the second time, it works well, and I upload the file successfully, why? Is it have any delay when I call setDefaultHostnameVerifier()? If it is, how can I make it works for the first time I call upload() method? And can anybody tell me the principle of the method setDefaultHostnameVerifier()?
Related
I'm using AsyncTask class to connect with database. Based on data I will create dynamic EditText, Checkbox without involving XML file.
lView = new LinearLayout(this); - Here I'm facing with error!
Is there any way to call UI thread inside of doInBackground method!
Thanks in advance!!
#Override
protected String doInBackground(String... param) {
HashMap<String, bean> map = new HashMap<String, bean>();
try {
url = new URL("http://localhost/app/alldata.php");
} catch (MalformedURLException e) {
Toast.makeText(getApplicationContext(), "URL Exception", Toast.LENGTH_LONG).show();
e.printStackTrace();
return null;
}
try {
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("POST");
// setDoInput and setDoOutput method depict handling of both send and receive
conn.setDoInput(true);
conn.setDoOutput(true);
// Append parameters to URL
Uri.Builder builder = new Uri.Builder()
.appendQueryParameter("user_id", "user_id")
.appendQueryParameter("dpt_id","dptid");
String query = builder.build().getEncodedQuery();
// Open connection for sending data
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(query);
writer.flush();
writer.close();
os.close();
conn.connect();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
int response_code = conn.getResponseCode();
lView = new LinearLayout(this);
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
conn.disconnect();
}
return null;
}
You can call publishProgress() from doInBackground method and override onProgressUpdate which will be called on UI thread.
Obviously, this is intented for progress-like usage. You should have clearly separated one unit of work for background and then process it normally in onPostExecute.
If you really want to communicate with the main UI Thread you can use:
runOnUiThread(new Runnable() {
#Override
public void run() {
//place your code here
}
});
The more elegant way of doing this is passing a callback function so that when your AsyncTask finishes its job, it can invoke the method call in your Activity and then you can make necessary changes there.
I would like to suggest keeping an interface like this.
public interface HttpResponseListener {
void httpResponseReceiver(String result);
}
Now, in your Activity, you need to implement this listener and when executing your AsyncTask you need to pass the listener to that AsyncTask too.
public YourActivity extends Activity implements HttpResponseListener {
// ... Other functions
#Override
public void httpResponseReceiver(String result) {
int response_code = (int) Integer.parseInt(result);
// Take necessary actions here
lView = new LinearLayout(this);
}
}
Now in your AsyncTask you need to have a variable first as a listener to your Activity.
public class HttpRequestAsyncTask extends AsyncTask<Void, Void, String> {
// Declare the listener here
public HttpResponseListener mHttpResponseListener;
#Override
protected String doInBackground(String... param) {
HashMap<String, bean> map = new HashMap<String, bean>();
try {
url = new URL("http://localhost/app/alldata.php");
} catch (MalformedURLException e) {
Toast.makeText(getApplicationContext(), "URL Exception", Toast.LENGTH_LONG).show();
e.printStackTrace();
return null;
}
try {
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("POST");
// setDoInput and setDoOutput method depict handling of both send and receive
conn.setDoInput(true);
conn.setDoOutput(true);
// Append parameters to URL
Uri.Builder builder = new Uri.Builder()
.appendQueryParameter("user_id", "user_id")
.appendQueryParameter("dpt_id","dptid");
String query = builder.build().getEncodedQuery();
// Open connection for sending data
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(query);
writer.flush();
writer.close();
os.close();
conn.connect();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
// int response_code = conn.getResponseCode(); // Return the result to onPostExecute
// lView = new LinearLayout(this); // Remove this from here
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
conn.disconnect();
}
return conn.getResponseCode() + "";
}
// Set the result here
#Override
protected void onPostExecute(final String result) {
mHttpResponseListener.httpResponseReceiver(result);
}
}
Now from your Activity, when you're starting the AsyncTask you need to assign the listener first like this.
HttpRequestAsyncTask mHttpRequestAsyncTask = new HttpRequestAsyncTask();
mHttpRequestAsyncTask.mHttpResponseListener = YourActivity.this;
// Start your AsyncTask
mHttpRequestAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
Hope that helps!
In my android application I am trying to save some data in MongoDB database. I using this code (given below) for that. This code is displaying Toast that data is saved, but the data is not present in my database. I am not getting any exception. so kindly tell what can be the problem?
Code:
#Override
protected Boolean doInBackground(String... reminder) {
try {
URL requestUrl = new URL("MongoDB address");
HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.connect();
OutputStream save = connection.getOutputStream();
save.write(reminder[0].getBytes());
save.close();
connection.disconnect();
new Handler(context.getMainLooper()).post(new Runnable() {
public void run() {
Toast.makeText(context, "data is saved", Toast.LENGTH_LONG).show();
}
});
}
catch(Exception exception) {
Log.e("ERROR", "DB Saving", exception);
}
return true;
}
I use XWalkView by Crosswalk for displaying web page in my Android application. I tried to use sessions on my webpage but sessions simply don't work, I cannot save any session.
this is how I initialize XWalkView:
xWalkWebView = (XWalkView)findViewById(R.id.page);
xWalkWebView.setResourceClient(new MyResourceClient(xWalkWebView));
xWalkWebView.load(API.BASE_URL, null);
if(me.beesafe.beesafe.app.AppInfo.isDebug) {
// turn on debugging
XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, true);
}
and this is MyResouceClient:
class MyResourceClient extends XWalkResourceClient {
MyResourceClient(XWalkView view) {
super(view);
}
private InputStream inputStream;
private String builtDataString() throws IOException {
return "key=test";
}
private void writeDataToBuffer(ByteArrayOutputStream stream) throws IOException {
stream.write(this.builtDataString().getBytes());
stream.flush();
stream.close();
}
private void writeOutputStream(OutputStream output, ByteArrayOutputStream buffer) throws IOException {
byte[] bufferArray = buffer.toByteArray();
for(int i = 0; i < bufferArray.length; i++) {
output.write(bufferArray[i]);
}
output.flush();
output.close();
}
public String getContentType() {
return "application/x-www-form-urlencoded";
}
public String createBoundary() {
return "--------------------"
+ Long.toString(System.currentTimeMillis(), 16);
}
#Override
public WebResourceResponse shouldInterceptLoadRequest(XWalkView view, String urlStr) {
HttpURLConnection connection = null;
inputStream = null;
try {
if(urlStr.equalsIgnoreCase(API.BASE_URL)) {
URL url = new URL(urlStr);
connection = (HttpURLConnection) url.openConnection();
connection.setFixedLengthStreamingMode(this.builtDataString().getBytes().length);
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setConnectTimeout(20 * 1000);
connection.setReadTimeout(30 * 1000);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", getContentType());
connection.setRequestProperty("Content-Language", "en-US");
connection.setRequestProperty("Connection", "keep-alive");
DataOutputStream outputStream = new DataOutputStream(
connection.getOutputStream());
ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream();
writeDataToBuffer(outputBuffer);
writeOutputStream(outputStream, outputBuffer);
inputStream = connection.getInputStream();
}
} catch (MalformedURLException e) {
e.printStackTrace();
inputStream = null;
} catch (IOException e) {
e.printStackTrace();
inputStream = null;
} finally {
/*if (connection != null) {
connection.disconnect();
}*/
}
if(/*inputStream != null*/urlStr.equalsIgnoreCase(API.BASE_URL)) {
return new WebResourceResponse(null, "utf-8", inputStream);
} else {
return super.shouldInterceptLoadRequest(view, urlStr);
}
}
}
and help please ? How to turn on sessions ?
If I simply use this PHP code on my website, it does not work:
<?php
session_start();
$_SESSION['test'] = 'test';
?>
THere is nothing in $_SESSION['test']
php session works in xwalkview, You have to put session_start(); at the begin of every php file what useing session.
I want to check progress of uploading file by HttpUrlConnection. How I can do this? I've tried to calculate bytes when writing data in OutputStream but it's wrong, cause real uploading happens only when I call conn.getInputStream(), so I need somehow to check inputStream. Here is my code:
public static void uploadMovie(final HashMap<String, String> dataSource, final OnLoadFinishedListener finishedListener, final ProgressListener progressListener) {
if (finishedListener != null) {
new Thread(new Runnable() {
public void run() {
try {
String boundary = getMD5(dataSource.size()+String.valueOf(System.currentTimeMillis()));
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.setCharset(Charset.forName("UTF-8"));
for (String key : dataSource.keySet()) {
if (key.equals(MoviesFragmentAdd.USERFILE)) {
FileBody userFile = new FileBody(new File(dataSource.get(key)));
multipartEntity.addPart(key, userFile);
continue;
}
multipartEntity.addPart(key, new StringBody(dataSource.get(key),ContentType.APPLICATION_JSON));
}
HttpEntity entity = multipartEntity.build();
HttpURLConnection conn = (HttpsURLConnection) new URL(URL_API + "/video/addForm/").openConnection();
conn.setUseCaches(false);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept-Charset", "UTF-8");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Cache-Control", "no-cache");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("Content-length", entity.getContentLength() + "");
conn.setRequestProperty(entity.getContentType().getName(),entity.getContentType().getValue());
OutputStream os = conn.getOutputStream();
entity.writeTo(os);
os.close();
//Real upload starting here -->>
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
//<<--
JsonObject request = (JsonObject) gparser.parse(in.readLine());
if (!request.get("error").getAsBoolean()) {
//do something
}
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
Because you have to deal with upload, I'd suppose most time is taken when doing entity.writeTo(os);. Maybe the first contact to the server takes some time as well (DNS resolution, SSL-handshake, ...). The markers you set for "the real upload" are not correct IMO.
Now it depends on your Multipart-library, whether you can intercept writeTo. If it is clever and resource-efficient, it's iterating over the parts and streams the content one-by-one to the output stream. If not, and the .build() operation is creating a big fat byte[], then you could take this array, stream it in chunks to the server and tell your user how many percent of the upload is already done.
From a resource perspective I'd prefer not really knowing what happens. But if feedback is that important and if the movies are only a few megabytes in size, you could stream the Multipart-Entity first to a ByteArrayOutputStream and then write little chunks of the created byte-array to the server while notifying your user about progress. The following code is not validated or tested (you can see it as pseudo-code):
ByteArrayOutputStream baos = new ByteArrayOutputStream();
entity.writeTo(baos);
baos.close();
byte[] payload = baos.toByteArray();
baos = null;
OutputStream os = conn.getOutputStream();
int totalSize = payload.length;
int bytesTransferred = 0;
int chunkSize = 2000;
while (bytesTransferred < totalSize) {
int nextChunkSize = totalSize - bytesTransferred;
if (nextChunkSize > chunkSize) {
nextChunkSize = chunkSize;
}
os.write(payload, bytesTransferred, nextChunkSize); // TODO check outcome!
bytesTransferred += nextChunkSize;
// Here you can call the method which updates progress
// be sure to wrap it so UI-updates are done on the main thread!
updateProgressInfo(100 * bytesTransferred / totalSize);
}
os.close();
A more elegant way would be to write an intercepting OutputStream which registers progress and delegates the real write-operations to the underlaying "real" OutputStream.
Edit
#whizzzkey wrote:
I've re-checked it many times - entity.writeTo(os) DOESN'T do a real upload, it does conn.getResponseCode() or conn.getInputStream()
Now it's clear. HttpURLConnection is buffering your upload data, because it doesn't know the content-length. You've set the header 'Content-length', but oviously this is ignored by HUC. You have to call
conn.setFixedLengthStreamingMode(entity.getContentLength());
Then you should better remove the call to conn.setRequestProperty("Content-length", entity.getContentLength() + "");
In this case, HUC can write the headers and entity.writeTo(os) can really stream the data to the server. Otherwise the buffered data is sent when HUC knows how many bytes will be transferred. So in fact, getInputStream() tells HUC that you're finished, but before really reading the response, all the collected data has to be sent to the server.
I wouldn't recommend changing your code, but for those of you who don't know the exact size of the transferred data (in bytes, not characters!!), you can tell HUC that it should transfer the data in chunks without setting the exact content-length:
conn.setChunkedStreamingMode(-1); // use default chunk size
Right this code in your activity...
public class PublishPostToServer extends AsyncTask implements
ProgressListenerForPost {
public Context pContext;
public long totalSize;
private String response;
public PublishPostToServer(Context context) {
pContext = context;
}
protected void onPreExecute() {
showProgressDialog();
}
#Override
protected Boolean doInBackground(Void... params) {
boolean success = true;
try {
response = NetworkAdaptor.getInstance()
.upLoadMultipartImageToServer(
"",
"",
"", this, this); // Add file path, Authkey, caption
} catch (Exception e) {
success = false;
}
return success;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
//validateResponse(result, response);
}
#Override
protected void onProgressUpdate(Integer... values) {
try {
if (mProgressDialog != null) {
mProgressDialog.setProgress(values[0]);
}
} catch (Exception exception) {
}
}
#Override
public void transferred(long num) {
publishProgress((int) ((num / (float) totalSize) * 100));
}
}
private void showProgressDialog() {
try {
String dialogMsg = "Uploading Image...";
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(dialogMsg);
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
mProgressDialog.show();
} catch (Exception exception) {
}
}
Now, Make a NetworkAdapter Class
public String upLoadMultipartImageToServer(String sourceFileUri,
String auth_key, String caption, ProgressListenerForPost listiner,
PublishPostToServer asyncListiner) {
String upLoadServerUri = "" + "upload_image";
HttpPost httppost = new HttpPost(upLoadServerUri);
File file = new File(sourceFileUri);
if (file.exists()) {
FileBody filebodyVideo = new FileBody(file);
CustomMultiPartEntity multipartEntity = new CustomMultiPartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE, listiner);
try {
multipartEntity.addPart("auth_key", new StringBody(auth_key));
multipartEntity.addPart("caption", new StringBody(caption));
multipartEntity.addPart("image", filebodyVideo);
asyncListiner.totalSize = multipartEntity.getContentLength();
httppost.setEntity(multipartEntity);
}
catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
DefaultHttpClient mHttpClient = new DefaultHttpClient();
String response = "";
try {
response = mHttpClient.execute(httppost,
new MovieUploadResponseHandler());
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return response;
} else {
return null;
}
}
#SuppressWarnings("rawtypes")
private class MovieUploadResponseHandler implements ResponseHandler {
#Override
public Object handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
HttpEntity r_entity = response.getEntity();
String responseString = EntityUtils.toString(r_entity);
// DebugHelper.printData("UPLOAD", responseString);
return responseString;
}
}
public static boolean isValidResponse(String resultData) {
try {
} catch (Exception exception) {
//DebugHelper.printException(exception);
}
return true;
}
public String upLoadVideoToServer(String currentFilePath, String string,
PublishPostToServer publishPostToServer,
PublishPostToServer publishPostToServer2) {
// TODO Auto-generated method stub
return null;
}
I have this code from a book I have to learn about Android .. what's wrong?
I always get 01 Error Connecting which is an exception in my code while establishing http connection.
public class HttpImgActivity extends Activity {
private InputStream OpenHttpConnection(String urlString)
throws IOException
{
InputStream in = null; // creating My input
int response = -1;
URL url= new URL(urlString);
URLConnection conn = url.openConnection();
if(!(conn instanceof HttpURLConnection)) // if not a valid URL
throw new IOException ("NOT an Http connection");
try{
HttpURLConnection httpconn = (HttpURLConnection) conn;
httpconn.setAllowUserInteraction(false); // prevent user interaction
httpconn.setInstanceFollowRedirects(true);
httpconn.setRequestMethod("GET");
httpconn.connect(); //initiates the connection after setting the connection properties
response = httpconn.getResponseCode(); // getting the server response
if(response == HttpURLConnection.HTTP_OK ) // if the server response is OK then we start receiving input stream
{ in = httpconn.getInputStream(); }
} // end of try
catch(Exception ex)
{
throw new IOException(" 01 Error Connecting");
}
return in; // would be null if there is a connection error
} // end of my OpenHttpConnection user defined method
*/
private Bitmap DownloadImage(String URL)
{
Bitmap bitmap= null;
InputStream in = null;
try
{
in = getInputStreamFromUrl(URL);
bitmap = BitmapFactory.decodeStream(in);
in.close();
}
catch (IOException e1)
{
Toast.makeText(this, e1.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
return bitmap; // this method returns the bitmap which is actually the image itself
}
ImageView img;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Bitmap bitmap = DownloadImage("http://www.egyphone.com/wp-content/uploads/2011/05/Samsung_Galaxy_S_II_2.jpg");
img =(ImageView) findViewById(R.id.myImg);
img.setImageBitmap(bitmap);
}
}
Any ideas?
It seems you catch your exception, but you don't use it for anything.
Try changing throw new IOException(" 01 Error Connecting"); to throw new IOException(ex.toString());
And you should think about using Android's logging tools, instead to see your errors through logcat:
...
catch(Exception ex)
{
Log.e("CONNECTION", ex.toString(), ex);
}
...
This makes debugging easier IMO.