четверг, 28 июля 2011 г.

ANDROID сохранение фотографии с камеры (ANDROID saving photos from your camera )

Здравствуйте мальчики и девочки. Сейчас я вам расскажу историю!

Я занимаюсь разработкой игры для ANDROID, и потребовалось сделать фичу богунеугодную. Надо было из нашего приложения фоткать пользователя, сжимать фотографию до размера такого, чтобы пользователь не смог разглядеть на фотографии сколько у него глаз(1 или 2) и сделать эту картинку его аватарой в игре. Притом фича должна позволять выбирать картинку как тока что сделанную с фотика, так и просто выбрав картинку из памяти. Пользователю конечно 5 секунд экономии, программисту -10 000 нейронов. Ну да ладно история, не в этом.
Нашли, как это сделать, была программуля, которая при запуске сразу запускала камеру и при клике по экрану фоткала и сохраняла фотографию.
В манифесте прописываем разрешение использовать камеру из приложения.
< uses-permission android:name="android.permission.CAMERA" > </uses-permission >

Вот и сорцы собственно.

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Environment;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;

public class CamaraView extends Activity implements SurfaceHolder.Callback, OnClickListener {

static final int FOTO_MODE = 0;
Camera mCamera;
boolean mPreviewRunning = false;
private Context mContext = this;



public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.camaraview);

mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
mSurfaceView.setOnClickListener(this);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}



@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}



Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera c) {

if (imageData != null) {

Intent mIntent = new Intent();

StoreByteImage(mContext, imageData, 100, 58, 58, "ImageName");
mCamera.startPreview();

setResult(FOTO_MODE, mIntent);
finish();
}
}
};



protected void onResume() {

super.onResume();
}



protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}



protected void onStop() {
super.onStop();
}



public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();

}



public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mPreviewRunning) {
mCamera.stopPreview();
}

Camera.Parameters p = mCamera.getParameters();
p.set("orientation", "portrait");
p.setPreviewSize(w, h);
mCamera.setParameters(p);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {}

mCamera.startPreview();
mPreviewRunning = true;
}



public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}



private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;



public void onClick(View arg0) {
mCamera.takePicture(null, mPictureCallback, mPictureCallback);

}



public static void StoreByteImage(Context mContext, byte[] imageData, int quality, int height, int weight, String expName) {

FileOutputStream fileOutputStream = null;
try{

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 5;

Bitmap myImage = BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options);
Bitmap myScaledImage = Bitmap.createScaledBitmap(myImage, height, weight, false);

fileOutputStream = new FileOutputStream(Environment.getExternalStorageDirectory().toString() + "/" + expName + ".jpg");

BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);

myScaledImage.compress(CompressFormat.JPEG, quality, bos);

bos.flush();
bos.close();
}
catch (IOException e) {}
}
}

Многовато, да? Ну мы радовалась что программуля работает, фоткает и сохраняет. Но вот беда. Привет разработчикам android'a, чтобы вы находились в try и вас выкинуло исключением в космос нахер!!!
Объясняю, почему я так злюсь. Когда мы начали прикручивать вызов этого диалога, по кнопке картинка не сохранялась. Как только мы не изменяли код, откуда тока его не брали. В интернете куча способов и все разные, я считаю это как минус, так и плюс, хотя для нас было это большим минусом, т.к сбивало нас с толку, всё ли верно в коде мы делаем. Потом, прошарив кучу страничек что выдал google, я натолкнулся на строчку, которую надо прописать в манифесте твоего приложения, которая позволяет приложению сохранять или изменять файлы.
< uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" / > 

Вот она. Так какого хрена та програмуля работала без этой строчки, если делать это можно лишь с разрешения, то не зависимо главное это окно или вызов диалога. В общем ребятки надеюсь вам это поможет.