2013年12月16日月曜日

画像をPOST送信する

通信部分でハマったのでメモします。
HTTP接続開始で何故かexceptionが発生し、マニュフェストファイルのインターネット設定もしているのに全く原因がわからず…困り果ててこの記事を発見しました。…orz

4.*系の端末で、POSTをつかって画像をUPする方法について。
原因
4.x系から通信処理系はバックグラウンドからのみ許可するとの事でした。
…2.x系の実機端末で確認すると確かに動作していました。(@w@;)


AsyncTascバックグラウンド処理に切り替える事に(@_@`)

ようやく、アンドロイド端末のギャラリーから画像を選択しPOSTする事が出来ました。。(@▽@)ホッ
◆通信部分
private static final String BOUNDARY = "----------V2ymHFg03ehbqgZCaKO6jy";
 private String url;
 private List<NameValuePair> postData;
 private String imageName;
 private String imagePath;
 private String METHOD_POST = "POST";
 private String METHOD_GET = "GET";
 private String USER_AGENT = "Android";
 
 //コンストラクタ
 public RequeatEx(
  String url, List<NameValuePair> postData,
  String imageName, String imagePath) {
  this.url = url;
  this.postData = postData;
  this.imageName = imageName;
  this.imagePath = imagePath;
 }


try{
   //basic認証 (注意)openConnection前に記述する ***************************
   final String username = "****";
   final String password = "****";
   Authenticator.setDefault(new Authenticator(){
    @Override protected PasswordAuthentication getPasswordAuthentication(){
     return new PasswordAuthentication(username, password.toCharArray());
    }
   });
   //******************************************************************
   
   StringBuffer sb = new StringBuffer();
   sb.append("multipart/form-data");//画像送信する時はマルチパート
   sb.append(";boundary="+BOUNDARY);//データの境界線
   
   conn = new URL(url).openConnection();
   conn.setRequestProperty("Content-Type", sb.toString() );
   // User Agentの設定はAndroid1.6の場合のみ必要  [String : "Android" ]
   conn.setRequestProperty("User-Agent", USER_AGENT );
   // HTTP POSTのための設定  [String : "POST" or "GET" ]
   ((HttpURLConnection)conn).setRequestMethod( METHOD_POST );
   conn.setDoOutput(true);
   // HTTP接続開始
   conn.connect();
   
   // send post data
   File file =new File(imagePath);
   OutputStream os = conn.getOutputStream();
   os.write(createBoundaryMessage(file.getName()).getBytes());
   os.write(getImageBytes(file));
   String endBoundary = "\r\n--" + BOUNDARY + "--\r\n";
   os.write(endBoundary.getBytes());
   os.close();
  
   // get response
   InputStream is = conn.getInputStream();
   res = convertToString(is);
   
 }catch(Exception e){
   Log.d("HttpMultipartRequest:", e.getMessage());
 }finally{
   //HTTP接続終了
   if (conn != null ){
    ((HttpURLConnection)conn).disconnect();
   }
 }


//コピーして使わせていただきました(^_^)
private String createBoundaryMessage(String fileName) {
  
 StringBuffer res = new StringBuffer("--").append(BOUNDARY).append("\r\n");
  
 for (NameValuePair nv : postData) {
  res.append("Content-Disposition: form-data; name=\"").append(nv.getName()).append("\"\r\n")    
  .append("\r\n").append(nv.getValue()).append("\r\n")
  .append("--").append(BOUNDARY).append("\r\n");
 }
  
 String[] fileChunks = fileName.split("\\.");
 String fileType = "image/" + fileChunks[fileChunks.length - 1];
 res.append("Content-Disposition: form-data; name=\"")
 .append(imageName)
 .append("\"; filename=\"").append(fileName).append("\"\r\n") 
 .append("Content-Type: ").append(fileType).append("\r\n\r\n");
  
 return res.toString();
}

private byte[] getImageBytes(File file) {
 byte[] b = new byte[10];
 FileInputStream fis = null;
 ByteArrayOutputStream bo = new ByteArrayOutputStream();
 try{
   
  fis = new FileInputStream(file);
  while(fis.read(b) &gt; 0) {
  bo.write(b);
 }
   
  }catch(FileNotFoundException e){
   Log.d("HttpMultipartRequest:", e.getMessage());
  }catch(IOException e){
   Log.d("HttpMultipartRequest:", e.getMessage());
  }finally{
   try { bo.close(); } catch (IOException e) {}
   if (fis != null) try { fis.close(); } catch (IOException e) {}
  }
  return bo.toByteArray();
 }

 private String convertToString(InputStream stream) {
  InputStreamReader streamReader = null;
  BufferedReader bufferReader = null;
  try {
   streamReader = new InputStreamReader(stream, "UTF-8");
   bufferReader = new BufferedReader(streamReader);
   StringBuilder builder = new StringBuilder();
   for (String line = null; (line = bufferReader.readLine()) != null;) {
    builder.append(line).append("\n");
   }
   return builder.toString();
  
  }catch(UnsupportedEncodingException e){
  
   Log.e("HttpMultipartRequest:", e.getMessage());
  
  }catch(IOException e){
   Log.e("HttpMultipartRequest:", e.toString());
  
  }finally{
   try{
    stream.close();
    if (bufferReader != null) bufferReader.close();
    } catch(IOException e) {}
  }
  return null;
 }




◆非同期部分                                                                                              ^__^
  AsyncTaskを継承したクラスを作成するべし、するべし、するべし~(@ω@)
public class AsyncTaskEx extends AsyncTask<String> implements OnCancelListener{
 final String TAG = "AsyncTaskEx";
 ProgressDialog dialog;
 Context context;

 public AsyncTaskEx(Context context){
  this.context = context;
 }

 /*
  * ダイアログの表示
  */
 @Override
 protected void onPreExecute() {
  Log.d(TAG, "onPreExecute");
  dialog = new ProgressDialog(context);
  dialog.setTitle("Please wait");
  dialog.setMessage("Loading data...");
  dialog.setCancelable(true);
  dialog.setOnCancelListener(this);
  dialog.setMax(100);
  dialog.setProgress(0);
  dialog.show();
  
 }

 /*
  * UI threadに関わる処理を記述すると、実行時にエラーとなるので注意
  * 
  * ダイアログの表示/非表示や取得データの表示といった、画面の描画を伴うような処理
  * 記述せずに、onPreExecute()やonPostExecute()に記述する必要あり
  */
 @Override
 protected String doInBackground(String... params){
  Log.d(TAG, "doInBackground - " + params[0]);

  if(isCancelled()){
   Log.d(TAG, "Cancelled!");
  }
  
  String response = null;
  
  try {
   /*
    * post送信
    */
   
   Thread.sleep(1000);
   
   RequeatEx request = new RequeatEx(
    "http://************************",//POST先
    new ArrayList(),//POSTする配列
    "upload-file",
    params[0]
   );
   Log.d( "request", "send");
   response = request.send();
  
  }catch(Exception e){
   Log.e(TAG, e.getMessage());
  }
  
  return response;
 }

 
 @Override
 protected void onProgressUpdate(Integer... values) {
  Log.d(TAG, "onProgressUpdate - " + values[0]);
  }

 @Override
 protected void onCancelled() {
  Log.d(TAG, "onCancelled");
  dialog.dismiss();
 }

 
 /*
  * データの整形→表示と、ダイアログの非表示
  */
 @Override
 protected void onPostExecute(String result) {
  Log.d(TAG, "onPostExecute - " + result);
  dialog.dismiss();
 }

 @Override
 public void onCancel(DialogInterface dialog) {
  Log.d(TAG, "Dialog onCancell... calling cancel(true)");
  this.cancel(true);
 }
 
}




◆アクティビティ
  

 /*
  * 標準ギャラリーから戻り時に呼ばれるイベント
  */
 protected void onActivityResult( int requestCode, int resultCode, Intent data ){
  super.onActivityResult( requestCode, resultCode, data );
  if( requestCode == REQUEST_PICK_CONTANT &amp;&amp; resultCode == RESULT_OK ){
   Log.d("activity mehotd", "データ取得成功");
   Log.d( "activity", "onActivityResult data = "+data.getData() );
   
   ImageView img = (ImageView) findViewById( R.id.girl_image_display );
   img.setImageURI(data.getData());
   
   //Uri→fileへ変換処理
   //content:/************ ⇒ file:/******************** の形へ変換する
   Cursor c = getContentResolver().query(data.getData(), null, null, null, null);
   c.moveToFirst();
   String filename = c.getString(c.getColumnIndex(MediaStore.MediaColumns.DATA));

   
   //Log.d( "data uri", data.getDataString() );
   //Log.d( "data file_path", filename );
   
   new AsyncTaskEx(this).execute(filename);
   
  }
 }
 
 /*
  * 参照ボタンクリックイベント
  */
 public void onClickPost( View view ){
   
  //暗黙インテントでSD画像ギャラリーを取得する
  Intent intent_gallery   =  new Intent(Intent.ACTION_PICK);
  intent_gallery.setType( "image/*" );//タイプの設定
  startActivityForResult(intent_gallery, REQUEST_PICK_CONTANT );
 }





★参考サイト☆
Android でライブラリの追加無しでマルチパート POST する方法Add Star
AsyncTask を利用した非同期処理

0 件のコメント:

コメントを投稿