Upload
claude-falguiere
View
418
Download
2
Tags:
Embed Size (px)
Citation preview
@cfalguiere
Android Camera the making of
MarsJUG
Aix en Provence - Marseille6 Décembre 2012
jeudi 6 décembre 12
@cfalguiere
Claude FalguièreArchitecte Technique Valtech
http://cfalguiere.wordpress.com
Duchess France, Paris JUG, Devoxx4Kids
jeudi 6 décembre 12
@cfalguiere
Objectif questions apprendre
gadget fun pour Devoxx
alimenter un hacker space Duchess
jeudi 6 décembre 12
@cfalguiere
ADT : Eclipse + Plugins ADT + SDK
http://developer.android.com
IDE
Eclipse
jeudi 6 décembre 12
@cfalguiere
ADT : Eclipse + Plugins ADT + SDK
http://developer.android.com
IDE
Plugins
jeudi 6 décembre 12
@cfalguiere
ADT : Eclipse + Plugins ADT + SDK
http://developer.android.com
IDE
Platform Tools
jeudi 6 décembre 12
@cfalguiere
Android Virtual Device (AVD)IDE
jeudi 6 décembre 12
@cfalguiere
Activity
TextView
Hello World
Hello WorldHelloonCreateonPauseonResumeonDestroy
GroupView(layout)
jeudi 6 décembre 12
@cfalguiere
Hello WorldActivity GroupView(layout)
TextView
Go
Hello World
ImageView
Button
Hello
jeudi 6 décembre 12
@cfalguiere
(layout)
CameraCamera
SurfaceView
SurfaceHolder
Activity
jeudi 6 décembre 12
@cfalguiere
(layout)
CameraCamera
SurfaceHolder
Activity SurfaceView
jeudi 6 décembre 12
@cfalguiere
Camera
RelativeLayoutActivity
Camera
CameraPreview
SurfaceHolder
openrelease
Camera
surfaceCreatedsurfaceDestroyedsurfaceChanged
startPreviewstopPreview
SurfaceView
jeudi 6 décembre 12
@cfalguiere
Camera
RelativeLayoutActivity
CameraPreview
SurfaceView
FrameLayout
jeudi 6 décembre 12
@cfalguiere
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" >
<FrameLayout android:id="@+id/cameraPreviewFrame" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" > </FrameLayout>
<Button android:id="@+id/saveButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:background="@drawable/camera_icon" android:onClick="whenSave" />
</RelativeLayout>
layout/main_activity.xmlCamera
jeudi 6 décembre 12
@cfalguiere
public CameraPreview(Context context, Camera camera) { super(context); mCamera = camera; mHolder = getHolder(); mHolder.addCallback(this);
...
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCamera = Camera.open();
CameraPreview cameraPreview = new CameraPreview(this, mCamera); FrameLayout previewFrame = (FrameLayout) findViewById(R.id.cameraPreviewFrame); previewFrame.addView(cameraPreview); ...
MainActivity.java
CameraPreview.java
Camera
jeudi 6 décembre 12
@cfalguiere
Camera manifest.xml
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.duchescamera" android:versionCode="1" android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:screenOrientation="landscape"> <activity android:name="com.example.duchescamera.MainActivity" android:label="@string/app_name" > ...
jeudi 6 décembre 12
@cfalguiere
Camera manifest.xml
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.duchescameramini2" android:versionCode="1" android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
<!-- will make use of camera --> <uses-feature android:name="android.hardware.camera" android:required="true" /> <uses-permission android:name="android.permission.CAMERA" />
jeudi 6 décembre 12
@cfalguiere
CameraRelativeLayout
SurfaceView
Orientation par défaut du device
Orientation par défaut de la camera
jeudi 6 décembre 12
@cfalguiere
opensetCameraDisplay (holder)
startPreview
takePicture
stopPreview
release
jeudi 6 décembre 12
@cfalguiere
Photo
<Button android:id="@+id/saveButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:background="@drawable/camera_icon" android:onClick="whenSave" />
layout/main_activity.xml
jeudi 6 décembre 12
@cfalguiere
PhotoActivity
whenSave
public void whenSave(View view) { mCamera.takePicture(shutterCallback, null, jpegPictureCallback); }
CameratakePicture
ShutterCallback RawCallback PictureCallback
onShutteronPictureTaken
MainActivity.java
«Click» générer le fichier
jeudi 6 décembre 12
@cfalguiere
public void whenSave(View view) { Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() { public void onShutter() { mSoundPool.play(mShutterSoundId, mShutterSoundVolume, mShutterSoundVolume, 1, 0, 1); } }; mCamera.takePicture(shutterCallback, null, mJpegPictureCallback); ...
private SoundPool mSoundPool; private int mShutterSoundId; private float mShutterSoundVolume = 0.5f;
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); mShutterSoundId = mSoundPool.load(this, R.raw.camera_click, 1); ...
MainActivity.javaPhoto
jeudi 6 décembre 12
@cfalguiere
public void onPictureTaken(byte[] data, Camera camera) { try { Bitmap photo = BitmapFactory.decodeByteArray(data, 0,data.length);
// Create a new, empty bitmap with the original size. Bitmap bitmap = Bitmap.createBitmap(photo.getWidth(),
photo.getHeight(), photo.getConfig()); Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(photo, 0, 0, null);
// save file File pictureFile = getOutputMediaFile(); FileOutputStream fos = new FileOutputStream(pictureFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos); addPictureToGalery(pictureFile.getPath());
} catch (Exception e) { Log.d(TAG, "ERROR Could not save picture: " + e.getMessage()); } }
PictureCallbackPhoto
jeudi 6 décembre 12
@cfalguiere
private void addPictureToGalery(String path) { Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); Uri contentUri = Uri.fromFile(new File(path)); mediaScanIntent.setData(contentUri); mActivity.sendBroadcast(mediaScanIntent); }
PictureCallbackPhoto
jeudi 6 décembre 12
@cfalguiere
ImageView
Incrustation
Activity
CameraPreview
SurfaceView
FrameLayout
RelativeLayout
DrawView
onDraw
jeudi 6 décembre 12
@cfalguiere
DrawPreview
onDraw
draw
Canvas
DuchessSprite
x
y
Incrustation
jeudi 6 décembre 12
@cfalguiere
DrawPreview
onDraw
draw
draw
Canvas
MoveFeedbackSprite
RotationFeedbackSprite
draw
DuchessSprite
Incrustation
jeudi 6 décembre 12
@cfalguiere
private Bitmap bitmap; // the actual bitmap public void draw(Canvas canvas, float ratio) { Matrix matrix = new Matrix(); float s = 1 / bitmapScale; int cw = Math.round(bitmap.getWidth() / 2); int ch = Math.round(bitmap.getHeight() / 2);
canvas.drawBitmap(bitmap, matrix, null); }
DuchessSprite.javaIncrustation
jeudi 6 décembre 12
@cfalguiere
private Bitmap bitmap; // the actual bitmap public void draw(Canvas canvas, float ratio) { Matrix matrix = new Matrix(); float s = 1 / bitmapScale; int cw = Math.round(bitmap.getWidth() / 2); int ch = Math.round(bitmap.getHeight() / 2); matrix.setScale(s, s, cw, ch); canvas.drawBitmap(bitmap, matrix, null); }
DuchessSprite.javaIncrustation
jeudi 6 décembre 12
@cfalguiere
private Bitmap bitmap; // the actual bitmap public void draw(Canvas canvas, float ratio) { Matrix matrix = new Matrix(); float s = 1 / bitmapScale; int cw = Math.round(bitmap.getWidth() / 2); int ch = Math.round(bitmap.getHeight() / 2); matrix.setScale(s, s, cw, ch); matrix.postTranslate(centerX - cw, centerY - ch); canvas.drawBitmap(bitmap, matrix, null); }
DuchessSprite.javaIncrustation
jeudi 6 décembre 12
@cfalguiere
private Bitmap bitmap; // the actual bitmap public void draw(Canvas canvas, float ratio) { Matrix matrix = new Matrix(); float s = 1 / bitmapScale; int cw = Math.round(bitmap.getWidth() / 2); int ch = Math.round(bitmap.getHeight() / 2); matrix.setScale(s, s, cw, ch); matrix.postTranslate(centerX - cw, centerY - ch); matrix.postScale(ratio, ratio);
canvas.drawBitmap(bitmap, matrix, null); }
DuchessSprite.javaIncrustation
jeudi 6 décembre 12
@cfalguiere
public boolean onTouchEvent(MotionEvent event) { final int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { mDuchess.handleActionDown((int)event.getX(), (int)event.getY()); // update touched break; } case MotionEvent.ACTION_MOVE: { if (mDuchess.isTouched()) { mDuchess.setCenterX((int)event.getX()); mDuchess.setCenterY((int)event.getY()); invalidate(); } break; } case MotionEvent.ACTION_UP: { if (mDuchess.isTouched()) { mDuchess.setTouched(false); } reak; } } return true; }
DrawView.java
jeudi 6 décembre 12
@cfalguiere
public DrawView(Context context, DuchessSprite duchess) { super(context); ... // make the Panel focusable so it can handle events setFocusable(true); setFocusableInTouchMode(true); }
DrawView
IncrustationonTouchEvent
jeudi 6 décembre 12
@cfalguierejeudi 6 décembre 12
@cfalguiere
Installer ADT http://developer.android.com/sdk/index.html
Installer git (préférable)
http://developer.android.com
Lab 0
jeudi 6 décembre 12
@cfalguiere
Lab 1 Créez un repo Git (git init)
Créez un workspace Eclipse sur la racine du repo
Créez un projet dans Eclipse• New «Android Application Project»• (Facultatif) choisissez l’icone Photo dans Clipart• une activité MainActivity par défaut
Lancez l’application dans le simulateur• Créez un AVD Galaxy Nexus• Exécutez dans le simulateur
Lancez l’application sur un device connecté
jeudi 6 décembre 12
@cfalguiere
Lab 2Affichez la caméra dans votre application
vous aurez besoin • de modifier le layout (RelativeLayout et
FrameLayout)• d’implémenter un SurfaceView • de la feature android.hardware.camera• de la permission android.permission.CAMERA• de corriger l’orientation
jeudi 6 décembre 12
@cfalguiere
Lab 3Ajoutez le bouton et prennez une photo(Facultatif) ajoutez le son
vous aurez besoin • du composant graphique Button• de l’icône du bouton : drawable/camera_icon.png• de l’implémentation du PictureCallback • de la permission
android.permission.WRITE_EXTERNAL_STORAGE
• du fichier son camera_click.ogg (Facultatif)• de la classe SoundPool (Facultatif)
jeudi 6 décembre 12
@cfalguiere
Lab 4Ajoutez une vue ImageView custom et affichez Duchess
vous aurez besoin • de l’image du sprite : drawable/
duchessfr_shadow.png• de l’implémentation du Sprite DuchessSprite
jeudi 6 décembre 12
@cfalguiere
Lab 5Ajoutez la possibilité de déplacer le sprite
(Facultatif) affichez un feedback visuel
vous aurez besoin • de l’implémentation du Sprite DragFeedbackSprite
(Facultatif)
jeudi 6 décembre 12