0

このアクティビティでは、ユーザーがギャラリーから 1 つの画像を選択するか、写真を撮って (他のデータと共に) Web サイトにアップロードすることができます。

これまでのところ、2 つの異なる問題に遭遇しました。

1)ギャラリーの画像で試してみると、メッセージ /external/images/media/2305: open failed: ENOENT (No such file or directory) で IOException が発生します。これは、ファイル ストリームを開くときに発生します。

2)写真を撮ってみるとOKなのですが、暗号化されたデータ列が「AAAAAAAAAAAAAAAAAAAAAAAAAAA」(本当に長いですが、Aだけ)で構成されており、これは良くない兆候だと思います。ウェブサイトにまだ適切にアップロードできないため、これは推測にすぎませんが、同じデータ文字列を示す別の写真が変なにおいがするだけです。

コードはこちら

@Override

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
    case TAKE_PICTURE:
        if (resultCode == Activity.RESULT_OK) {
            //Uri selectedImage = imageUri;
            loadImage(imageUri);

    }
    break;
case SELECT_PHOTO:
    if(resultCode == Activity.RESULT_OK){  
        imageUri = data.getData();
        loadImage(imageUri);
    }
}
}

これは、画像(撮影した写真またはギャラリーから)をImageViewにロードする方法です。それは正常に動作します。

public void loadImage(Uri selectedImage){
    mActivity.getContentResolver().notifyChange(selectedImage, null);

    ContentResolver cr = mActivity.getContentResolver();
    Bitmap bitmap;
    try {
        bitmap = android.provider.MediaStore.Images.Media
                .getBitmap(cr, selectedImage);

        ivPicture.setImageBitmap(bitmap);
        ivPicture.setVisibility(View.VISIBLE);
        mActivity.croutonInfo(selectedImage.toString());

    } catch (Exception e) {
        mActivity.croutonAlert("Failed to load");
        e("Camera " + e.toString());
    }
}

これは、データのアップロードをモックするために使用する方法です。API を取得すると、http 転送を処理する asynctask が作成されます。これまでのところ、データは論理のない転送オブジェクトに入れられるだけです。

public void uploadTapa() throws IOException{
    mActivity.croutonInfo("subiendo tapa ");
    d("uploadTapa new ");
    TapaUploadParametros tup = new TapaUploadParametros();
    d("uploadTapa bar: " + nombreBar);
    tup.setBarNombre(etBarName.getText().toString());
    d("uploadTapa tapa: " + nombreTapa);
    tup.setNombre(etTapaName.getText().toString());
    d("uploadTapa municipio: " + municipio);
    tup.setLocalidad(municipio);
    d("uploadTapa provincia: " + provincia);
    tup.setProvincia(provincia);
    d("uploadTapa tipologiaId: " + tipologiaId);
    tup.setTipo(tipologiaId);
    d("uploadTapa precioId: " + precioId);
    tup.setPrecio(precioId);

    String encodedImage = encodeImgForHTTP(imageUri);
    d("uploadTapa encoded image: " + encodedImage);
    tup.setPic(encodedImage);
    d("uploadTapa direccionBar: " + direccionBar);
    tup.setBarDireccion(direccionBar);
}

そして、これが http 転送用に画像をエンコードする方法です。「ストリームを開く前」の直後にギャラリーからの画像が失敗する

   private String encodeImgForHTTP (Uri imageUri) throws IOException{
        ContentResolver cr = mActivity.getContentResolver();
        d("encodeImgForHTTP before opening stream ");
        FileInputStream fis = new FileInputStream(imageUri.getPath());
        d("encodeImgForHTTP after opening stream ");
        // Get binary bytes for encode
        byte[] imageBytes = new byte[fis.available()];
        d("encodeImgForHTTP after getting byte array ");
        // base 64 encode for text transmission (HTTP)
        d("encodeImgForHTTP pre 64: " + imageBytes);
        String data_string = Base64.encodeToString(imageBytes, Base64.URL_SAFE); 
        d("encodeImgForHTTP before returning the encoded data string " + data_string);
        return data_string;
    }

ギャラリーの画像で何が間違っていますか? 異なる画像のエンコーディングが同じに見えるのはなぜですか?

4

2 に答える 2

1

入力ストリームをより小さなバイト配列にバッファリングする必要があると思いますavailable。最初は、エンコーディング関数で推定値であるため、関数を使用しないでください。

写真を撮るには、画像を保存するパスを決定し、それをインテントのエクストラとして渡す必要があります。次に例を示します。

private void capture(){
    String directoryPath = Environment.getExternalStorageDirectory() + "/" + IMAGE_DIRECTORY + "/";
    String filePath = directoryPath+Long.toHexString(System.currentTimeMillis())+".jpg";
    File directory = new File(directoryPath);
    if (!directory.exists()) {
        directory.mkdirs();
    }
    this.capturePath = filePath; // you will process the image from this path if the capture goes well
    Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra( MediaStore.EXTRA_OUTPUT, Uri.fromFile( new File(filePath) ) );
    startActivityForResult(intent, REQUEST_CAPTURE);                

}
于 2013-03-15T12:09:33.937 に答える
0

やっと稼働できたのかな。まず、Emil のアドバイスに従って画像を保存しました。DCIM_PATH は、DCIM フォルダーへのパスです。

public void takePhoto() {
    String directoryPath = DCIM_PATH;
    d("takePhoto directoryPath: " + directoryPath);
    this.pictureFileName = Long.toHexString(System.currentTimeMillis())+".jpg";
    String filePath = directoryPath + pictureFileName ;
    File directory = new File(directoryPath);
    if (!directory.exists()) { // in case there's no DCIM folder
        directory.mkdirs(); // just create it
    }
    d("takePhoto filePath: " + filePath);
    this.imageUri = Uri.parse(filePath);
    d("takePhoto imageUri: " + filePath);
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            // here's where I tell the intent where to save the file
    intent.putExtra( 
            MediaStore.EXTRA_OUTPUT,Uri.fromFile( new File(filePath) )
            );

    startActivityForResult(intent, TAKE_PICTURE);

}

画像をイメージビューにロードするには、2 つの異なる方法を使用する必要がありました。撮影したばかりの写真の場合は、次の写真を使用します。

public void loadImageJustTaken(Uri selectedImage) {
    mActivity.getContentResolver().notifyChange(selectedImage, null);

    Bitmap bitmap = 
            BitmapFactory.decodeFile(imageUri.getPath());

    ivPicture.setImageBitmap(bitmap);
    ivPicture.setVisibility(View.VISIBLE);
}

しかし、ギャラリーから 1 つを使用するには、contentResolver を使用する必要があります

public void loadImage(Uri selectedImage){

    imageUri = selectedImage;
    mActivity.getContentResolver().notifyChange(selectedImage, null);

    ContentResolver cr = mActivity.getContentResolver();
    Bitmap bitmap;
    try {
        bitmap = android.provider.MediaStore.Images.Media
                .getBitmap(cr, imageUri);

        ivPicture.setImageBitmap(bitmap);
        ivPicture.setVisibility(View.VISIBLE);

        mActivity.croutonInfo(imageUri.getPath());

    } catch (Exception e) {
        e("Camera " + e.toString());
    }
}

画像をアップロードしたいときは、エンコードする必要があります。この方法は、正しいファイル パスを指定する限り機能します。

  private String encodeImgForHTTP (Uri imageUri) throws IOException{
    String realPicPath = getPath(imageUri);
    d("encodeImgForHTTP before opening stream " + realPicPath);
    FileInputStream fis = new FileInputStream(realPicPath);
    d("encodeImgForHTTP after opening stream ");
    // Get binary bytes for encode
    byte[] imageBytes = IOUtils.toByteArray(fis);
    d("encodeImgForHTTP after getting byte array ");

    // base 64 encode for text transmission (HTTP)
    //String data_string = Base64.encodeToString(data, Base64.URL_SAFE);
    d("encodeImgForHTTP pre 64: " + imageBytes);
    String data_string = Base64.encodeToString(imageBytes, Base64.URL_SAFE); 
    d("encodeImgForHTTP before returning the encoded data string " + data_string);
    return data_string;
}

そして、これが写真の「実際のパス」を取得する方法です。

public String getPath(Uri uri) throws IOException {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = mActivity.
            managedQuery(uri, projection, null, null, null);
    if (cursor == null){ // with pictures just taken, the uri returned by the onActivityResult makes cursor to be null. Following method takes care of that
        uri = saveMediaEntry(imageUri.getPath(), pictureFileName, "");
        d("cursor nulo, segundo cursor con uri " + uri.getPath());
        cursor = mActivity.
                managedQuery(uri, projection, null, null, null);
    }
    int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

メソッド saveMediaEntry は、その Uri を返すデバイスのメディア データベースへのエントリを作成します。その Uri を使用すると、カーソルは必要な画像ファイルを指すようになります

  private Uri saveMediaEntry(
        String imagePath,String title,String description) throws IOException {

    ExifInterface exif = new ExifInterface(imagePath);

    ContentValues v = new ContentValues();
    v.put(Images.Media.TITLE, title);
    v.put(Images.Media.DISPLAY_NAME, title);
    v.put(Images.Media.DESCRIPTION, description);
    v.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
    v.put(Images.Media.DATE_TAKEN, exif.getAttribute(ExifInterface.TAG_DATETIME));
    //v.put(Images.Media.DATE_MODIFIED, dateTaken) ;
    v.put(Images.Media.MIME_TYPE, "image/jpeg");
    v.put(Images.Media.ORIENTATION, exif.getAttribute(ExifInterface.TAG_ORIENTATION));
    File f = new File(imagePath) ;
    File parent = f.getParentFile() ;
    String path = parent.toString().toLowerCase() ;
    String name = parent.getName().toLowerCase() ;
    v.put(Images.ImageColumns.BUCKET_ID, path.hashCode());
    v.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, name);
    v.put(Images.Media.SIZE,f.length()) ;
    f = null ;

    v.put(Images.Media.LATITUDE, exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
    v.put(Images.Media.LONGITUDE, exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));

    v.put("_data",imagePath) ;
    ContentResolver c = mActivity.getContentResolver() ;
    return c.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, v);
}

このすべての後、写真は正常にロードされ、 Base64.encodeToString の戻り値は写真ごとに異なります:)

それが誰かを助けることを願っています:)

于 2013-03-19T07:54:46.200 に答える