2015-07-14 1 views
0

Я хочу сделать приложение, которое делает снимок и отправляет его на онлайн-сервер. Я прочитал много учебников и статей, и это мой код до сих пор:Android - отправить изображение на сервер - Async Task Произошла ошибка во время выполнения doInBackground()

import android.app.Activity; 
import android.content.Intent; 
import android.content.res.Configuration; 
import android.graphics.Bitmap; 
import android.net.Uri; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.os.Environment; 
import android.provider.MediaStore; 
import android.util.Log; 
import android.view.Menu; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.ImageView; 
import android.widget.Toast; 

import org.apache.http.HttpResponse; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.DefaultHttpClient; 

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.IOException; 
import java.io.InputStream; 
import java.text.SimpleDateFormat; 
import java.util.Date; 

public class MainActivity extends Activity implements OnClickListener { 
    private Button mTakePhoto; 
    private ImageView mImageView; 
    private static final String TAG = "upload"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     mTakePhoto = (Button) findViewById(R.id.take_photo); 
     mImageView = (ImageView) findViewById(R.id.imageview); 

     mTakePhoto.setOnClickListener(this); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.menu_main, menu); 
     return true; 
    } 

    @Override 
    public void onClick(View v) { 
     // TODO Auto-generated method stub 
     int id = v.getId(); 
     switch (id) { 
      case R.id.take_photo: 
       takePhoto(); 
       break; 
     } 
    } 

    private void takePhoto() { 
     Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
     startActivityForResult(cameraIntent, 1); 
    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     // TODO Auto-generated method stub 
     Log.i(TAG, "onActivityResult: " + this); 
     if (requestCode == REQUEST_TAKE_PHOTO && resultCode == Activity.RESULT_OK) { 
      Bitmap photo = (Bitmap) data.getExtras().get("data"); 
      mImageView.setImageBitmap(photo); 
      try { 
       sendPhoto(photo); 
      } catch (Exception e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 

    private void sendPhoto(Bitmap bitmap) throws Exception { 
     new UploadTask().execute(bitmap); 
    } 

    private class UploadTask extends AsyncTask<Bitmap, Void, Void> { 

     protected Void doInBackground(Bitmap... bitmaps) { 
      if (bitmaps[0] == null) 
       return null; 
      setProgress(0); 

      Bitmap bitmap = bitmaps[0]; 
      ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
      bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); // convert Bitmap to ByteArrayOutputStream 
      InputStream in = new ByteArrayInputStream(stream.toByteArray()); // convert ByteArrayOutputStream to ByteArrayInputStream 

      DefaultHttpClient httpclient = new DefaultHttpClient(); 
      try { 
       HttpPost httppost = new HttpPost(
         "http://xxxx/photo.php"); // server 

       MultipartEntity reqEntity = new MultipartEntity(); 
       reqEntity.addPart("myFile", 
         System.currentTimeMillis() + ".jpg", in); 
       httppost.setEntity(reqEntity); 

       Log.i(TAG, "request " + httppost.getRequestLine()); 
       HttpResponse response = null; 
       try { 
        response = httpclient.execute(httppost); 
       } catch (ClientProtocolException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       try { 
        if (response != null) 
         Log.i(TAG, "response " + response.getStatusLine().toString()); 
       } finally { 

       } 
      } finally { 

      } 

      if (in != null) { 
       try { 
        in.close(); 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 

      if (stream != null) { 
       try { 
        stream.close(); 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 

      return null; 
     } 

     @Override 
     protected void onProgressUpdate(Void... values) { 
      // TODO Auto-generated method stub 
      super.onProgressUpdate(values); 
     } 

     @Override 
     protected void onPostExecute(Void result) { 
      // TODO Auto-generated method stub 
      super.onPostExecute(result); 
      Toast.makeText(MainActivity.this, R.string.uploaded, Toast.LENGTH_LONG).show(); 
     } 
    } 

    @Override 
    protected void onResume() { 
     // TODO Auto-generated method stub 
     super.onResume(); 
     Log.i(TAG, "onResume: " + this); 
    } 

    @Override 
    protected void onPause() { 
     // TODO Auto-generated method stub 
     super.onPause(); 
    } 

    @Override 
    public void onConfigurationChanged(Configuration newConfig) { 
     // TODO Auto-generated method stub 
     super.onConfigurationChanged(newConfig); 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     // TODO Auto-generated method stub 
     super.onSaveInstanceState(outState); 
     Log.i(TAG, "onSaveInstanceState"); 
    } 

    String mCurrentPhotoPath; 

    static final int REQUEST_TAKE_PHOTO = 1; 
    File photoFile = null; 

    private void dispatchTakePictureIntent() { 
     Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
     // Ensure that there's a camera activity to handle the intent 
     if (takePictureIntent.resolveActivity(getPackageManager()) != null) { 
      // Create the File where the photo should go 
      File photoFile = null; 
      try { 
       photoFile = createImageFile(); 
      } catch (IOException ex) { 
       // Error occurred while creating the File 

      } 
      // Continue only if the File was successfully created 
      if (photoFile != null) { 
       takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, 
         Uri.fromFile(photoFile)); 
       startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO); 
      } 
     } 
    } 

    private File createImageFile() throws IOException { 
     // Create an image file name 
     String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
     String imageFileName = "JPEG_" + timeStamp + "_"; 
     String storageDir = Environment.getExternalStorageDirectory() + "/picupload"; 
     File dir = new File(storageDir); 
     if (!dir.exists()) 
      dir.mkdir(); 

     File image = new File(storageDir + "/" + imageFileName + ".jpg"); 

     // Save a file: path for use with ACTION_VIEW intents 
     mCurrentPhotoPath = image.getAbsolutePath(); 
     Log.i(TAG, "photo path = " + mCurrentPhotoPath); 
     return image; 
    } 

} 

MultipartEntity.java

import org.apache.http.Header; 
import org.apache.http.HttpEntity; 
import org.apache.http.message.BasicHeader; 

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 

public class MultipartEntity implements HttpEntity { 

    private String boundary = null; 

    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    boolean isSetLast = false; 
    boolean isSetFirst = false; 

    public MultipartEntity() { 
     this.boundary = System.currentTimeMillis() + ""; 
    } 

    public void writeFirstBoundaryIfNeeds(){ 
     if(!isSetFirst){ 
      try { 
       out.write(("--" + boundary + "\r\n").getBytes()); 
      } catch (final IOException e) { 

      } 
     } 
     isSetFirst = true; 
    } 

    public void writeLastBoundaryIfNeeds() { 
     if(isSetLast){ 
      return ; 
     } 
     try { 
      out.write(("\r\n--" + boundary + "--\r\n").getBytes()); 
     } catch (final IOException e) { 

     } 
     isSetLast = true; 
    } 

    public void addPart(final String key, final String value) { 
     writeFirstBoundaryIfNeeds(); 
     try { 
      out.write(("Content-Disposition: form-data; name=\"" +key+"\"\r\n").getBytes()); 
      out.write("Content-Type: text/plain; charset=UTF-8\r\n".getBytes()); 
      out.write("Content-Transfer-Encoding: 8bit\r\n\r\n".getBytes()); 
      out.write(value.getBytes()); 
      out.write(("\r\n--" + boundary + "\r\n").getBytes()); 
     } catch (final IOException e) { 

     } 
    } 

    public void addPart(final String key, final String fileName, final InputStream fin){ 
     addPart(key, fileName, fin, "application/octet-stream"); 
    } 

    public void addPart(final String key, final String fileName, final InputStream fin, String type){ 
     writeFirstBoundaryIfNeeds(); 
     try { 
      type = "Content-Type: "+type+"\r\n"; 
      out.write(("Content-Disposition: form-data; name=\""+ key+"\"; filename=\"" + fileName + "\"\r\n").getBytes()); 
      out.write(type.getBytes()); 
      out.write("Content-Transfer-Encoding: binary\r\n\r\n".getBytes()); 

      final byte[] tmp = new byte[4096]; 
      int l = 0; 
      while ((l = fin.read(tmp)) != -1) { 
       out.write(tmp, 0, l); 
      } 
      out.flush(); 
     } catch (final IOException e) { 

     } finally { 
      try { 
       fin.close(); 
      } catch (final IOException e) { 

      } 
     } 
    } 

    public void addPart(final String key, final File value) { 
     try { 
      addPart(key, value.getName(), new FileInputStream(value)); 
     } catch (final FileNotFoundException e) { 

     } 
    } 

    @Override 
    public long getContentLength() { 
     writeLastBoundaryIfNeeds(); 
     return out.toByteArray().length; 
    } 

    @Override 
    public Header getContentType() { 
     return new BasicHeader("Content-Type", "multipart/form-data; boundary=" + boundary); 
    } 

    @Override 
    public boolean isChunked() { 
     return false; 
    } 

    @Override 
    public boolean isRepeatable() { 
     return false; 
    } 

    @Override 
    public boolean isStreaming() { 
     return false; 
    } 

    @Override 
    public void writeTo(final OutputStream outstream) throws IOException { 
     outstream.write(out.toByteArray()); 
    } 

    @Override 
    public Header getContentEncoding() { 
     return null; 
    } 

    @Override 
    public void consumeContent() throws IOException, 
      UnsupportedOperationException { 
     if (isStreaming()) { 
      throw new UnsupportedOperationException(
        "Streaming entity does not implement #consumeContent()"); 
     } 
    } 

    @Override 
    public InputStream getContent() throws IOException, 
      UnsupportedOperationException { 
     return new ByteArrayInputStream(out.toByteArray()); 
    } 

} 

AndroidManifest:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.diana.data" > 

    <uses-permission android:name="android.permission.INTERNET" /> 
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
    <application 
     android:allowBackup="true" 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 

     <activity 
      android:name=".MainActivity" 
      android:label="@string/app_name" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

и мой PHP:

<?php 

// Path to move uploaded files 
$target_path = "http://xxxx/photos/"; 

// array for final json respone 
$response = array(); 

// getting server ip address 
$server_ip = gethostbyname(gethostname()); 

// final file url that is being uploaded 
$file_upload_url = 'http://' . $server_ip . '/' . 'AndroidFileUpload' . '/' . $target_path; 


if (isset($_FILES['image']['name'])) { 
    $target_path = $target_path . basename($_FILES['image']['name']); 


    $response['file_name'] = basename($_FILES['image']['name']); 
    $response['email'] = $email; 

    try { 
     // Throws exception incase file is not being moved 
     if (!move_uploaded_file($_FILES['image']['tmp_name'], $target_path)) { 
      // make error flag true 
      $response['error'] = true; 
      $response['message'] = 'Could not move the file!'; 
     } 

     // File successfully uploaded 
     $response['message'] = 'File uploaded successfully!'; 
     $response['error'] = false; 
     $response['file_path'] = $file_upload_url . basename($_FILES['image']['name']); 
    } catch (Exception $e) { 
     // Exception occurred. Make error flag true 
     $response['error'] = true; 
     $response['message'] = $e->getMessage(); 
    } 
} else { 
    // File parameter is missing 
    $response['error'] = true; 
    $response['message'] = 'Not received any file!F'; 
} 

// Echo final json response to client 
echo json_encode($response); 
?> 

Проблема что он падает, когда попадает на эту линию, и я понятия не имею, почему.

response = httpclient.execute(httppost); 

Это мой LogCat:

07-14 13:54:26.520 27507-28071/com.example.diana.data E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1 
    java.lang.RuntimeException: An error occured while executing doInBackground() 
      at android.os.AsyncTask$3.done(AsyncTask.java:299) 
      at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352) 
      at java.util.concurrent.FutureTask.setException(FutureTask.java:219) 
      at java.util.concurrent.FutureTask.run(FutureTask.java:239) 
      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
      at java.lang.Thread.run(Thread.java:841) 
    Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?) 
      at java.net.InetAddress.lookupHostByName(InetAddress.java:441) 
      at java.net.InetAddress.getAllByNameImpl(InetAddress.java:239) 
      at java.net.InetAddress.getAllByName(InetAddress.java:218) 
      at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:141) 
      at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
      at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
      at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360) 
      at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
      at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
      at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 
      at com.example.diana.data.MainActivity$UploadTask.doInBackground(MainActivity.java:116) 
      at com.example.diana.data.MainActivity$UploadTask.doInBackground(MainActivity.java:91) 
      at android.os.AsyncTask$2.call(AsyncTask.java:287) 
      at java.util.concurrent.FutureTask.run(FutureTask.java:234) 
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
            at java.lang.Thread.run(Thread.java:841) 
    Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname) 
      at libcore.io.Posix.getaddrinfo(Native Method) 
      at libcore.io.ForwardingOs.getaddrinfo(ForwardingOs.java:61) 
      at java.net.InetAddress.lookupHostByName(InetAddress.java:428) 
            at java.net.InetAddress.getAllByNameImpl(InetAddress.java:239) 
            at java.net.InetAddress.getAllByName(InetAddress.java:218) 
            at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:141) 
            at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
            at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
            at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360) 
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 
            at com.example.diana.data.MainActivity$UploadTask.doInBackground(MainActivity.java:116) 
            at com.example.diana.data.MainActivity$UploadTask.doInBackground(MainActivity.java:91) 
            at android.os.AsyncTask$2.call(AsyncTask.java:287) 
            at java.util.concurrent.FutureTask.run(FutureTask.java:234) 
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
            at java.lang.Thread.run(Thread.java:841) 
    Caused by: libcore.io.ErrnoException: getaddrinfo failed: EACCES (Permission denied) 
            at libcore.io.Posix.getaddrinfo(Native Method) 
            at libcore.io.ForwardingOs.getaddrinfo(ForwardingOs.java:61) 
            at java.net.InetAddress.lookupHostByName(InetAddress.java:428) 
            at java.net.InetAddress.getAllByNameImpl(InetAddress.java:239) 
            at java.net.InetAddress.getAllByName(InetAddress.java:218) 
            at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:141) 
            at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
            at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
            at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360) 
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 
            at com.example.diana.data.MainActivity$UploadTask.doInBackground(MainActivity.java:116) 
            at com.example.diana.data.MainActivity$UploadTask.doInBackground(MainActivity.java:91) 
            at android.os.AsyncTask$2.call(AsyncTask.java:287) 
            at java.util.concurrent.FutureTask.run(FutureTask.java:234) 
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
            at java.lang.Thread.run(Thread.java:841) 

Любые идеи/советы, что может быть проблема?

+0

Если у вас есть разрешение, вы можете разместить свой файл манифеста, пожалуйста. –

ответ

4

Как StackTrace сказал:

Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?) 

Вы должны добавить internet permission внутри манифеста файла.

<uses-permission android:name="android.permission.INTERNET" /> 

Другая проблема заключается в:

Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname) 

Возможно, вам нужно проверить имя хоста, которое вы используете для отправки запроса. (http://xxxx/photo.php)

+0

Я уже добавил. Это не проблема. – Diana

+2

@Edward, то вы добавили его неправильно. –

3

Ошибка конкретно говорит вам, что вам не хватает разрешения и слишком интернет.

Добавить разрешение INTERNET на ваш файл манифеста.

Вы должны добавить следующую строку:

<uses-permission android:name="android.permission.INTERNET" /> 

Еще одна проблема может быть, что вы можете добавлять разрешение неправильно или если это не так, то вам нужно проверить THIS ANSWER

Проверьте свой адрес хоста или Вы также можете попробовать, добавив это разрешение ниже интернета:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 
Смежные вопросы