Android Capture Image and Camera Capture Screenshot (android.view.SurfaceView) |
Android Capture Image and Camera Capture Screenshot (android.view.SurfaceView) บทความนี้เป็นการใช้งาน SurfaceView เพื่อเรียกให้ Camera หรือกล้องที่อยุ่บน Emulator และ Smartphone แสดงบนหน้าจอของ Application พร้อม ๆ กับการ Capture Screenshot และนำภาพที่ได้ไปใช้งานบน SD Card หรือ Application
SurfaceView and Camera Save Screenshot
ในบทความนี้จะทดสอบการเรียกใช้ Camera ด้วย SurfaceView และการ Capture หรือ Save Screenshot ภาพจากกล้อง โดยบันทึกไฟล์ที่ได้ลงบน SD Card พร้อม ๆ กับการนำภาพที่ได้แสดงบน ImageView
หลักการก็คือ ออกแบบ Form ขึ้นมา 2 Activity โดย Activity แรกจะสร้างปุ่ม Button สำหรับ Take Photo และหลังจากที่คลิก Take Photo จะทำการ Intent ไปยัง Activity ที่ 2 ซึ่งจะแสดงมุมมองของ SurfaceView ที่เป็น Camera และใน Activity นี้ผู้ใช้สามารถคลิกเพื่อ Save Screenshot และเมื่อได้ Screenshot ก็จะทำการปิดกล้อง พร้อม ๆ กับนำภาพที่ได้ไปแสดงใน Activity แรก
AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
ในตัวอย่างนี้มีการ Save ไฟล์ลงใน SD Card เพระาฉะนั้นจะต้องกำหนด Permission ในส่วนนี้ด้วย
โครงสร้างของไฟล์ใน Project
ไฟล์หลัก ๆ ประกอบด้วย 2 ไฟล์คือ MainActivity.java และ TakePhotoActivity.java ส่วนที่เหลือเป็น Class ที่จะเรียกใช้
ออกแบบ XML Layout ดังภาพ
activity_main.xml
<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" >
<Button
android:id="@+id/btnTakePhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="160dp"
android:text="Take Photo" />
<ImageView
android:id="@+id/imageShot"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="26dp"
android:layout_width="200dp"
android:layout_height="200dp"
android:src="@android:drawable/sym_def_app_icon" />
</RelativeLayout>
เป็น XML Layout ของหน้าแรกของ Application
/res/menu/activity_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/screenshot" android:title="Save Screenshot"></item>
<item android:id="@+id/cancel" android:title="Cancel"></item>
</menu>
เป็นไฟล์สำหรับ Menu ที่จะแสดงเป็น Save Screenshot และ Cancel
Element.java
package com.myapp;
import java.io.BufferedInputStream;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
public class Element {
private float mX;
private float mY;
private Bitmap mBitmap;
public Element(Resources res, int x, int y) {
mBitmap = BitmapFactory.decodeStream(new BufferedInputStream(res.openRawResource(R.drawable.icon)));
mX = x - mBitmap.getWidth() / 2;
mY = y - mBitmap.getHeight() / 2;
}
public void doDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, mX, mY, null);
}
}
Panel.java
package com.myapp;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
public static float mWidth;
public static float mHeight;
private ViewThread mThread;
private ArrayList<Element> mElements = new ArrayList<Element>();
private int mElementNumber = 0;
private Paint mPaint = new Paint();
private String mScreenshotPath;
public Panel(Context context,String fileName) {
super(context);
mScreenshotPath = fileName;
getHolder().addCallback(this);
mThread = new ViewThread(this);
mPaint.setColor(Color.WHITE);
}
public void doDraw(long elapsed, Canvas canvas) {
canvas.drawColor(Color.BLACK);
synchronized (mElements) {
for (Element element : mElements) {
element.doDraw(canvas);
}
}
canvas.drawText("FPS: " + Math.round(1000f / elapsed) + " Elements: " + mElementNumber, 10,
10, mPaint);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mWidth = width;
mHeight = height;
}
public void surfaceCreated(SurfaceHolder holder) {
if (!mThread.isAlive()) {
mThread = new ViewThread(this);
mThread.setRunning(true);
mThread.start();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mThread.isAlive()) {
mThread.setRunning(false);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
synchronized (mElements) {
mElements.add(new Element(getResources(), (int) event.getX(), (int) event.getY()));
mElementNumber = mElements.size();
}
return super.onTouchEvent(event);
}
/**
* If called, creates a screenshot and saves it as a JPG in the folder "picture" on the sdcard.
*/
public void saveScreenshot() {
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
doDraw(1, canvas);
File file = new File(mScreenshotPath);
FileOutputStream fos;
try {
fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
} catch (FileNotFoundException e) {
Log.e("Panel", "FileNotFoundException", e);
} catch (IOException e) {
Log.e("Panel", "IOEception", e);
}
}
/**
* close surface when canncel click
*/
public void CloseSurface() {
if (mThread.isAlive()) {
mThread.setRunning(false);
}
}
}
ViewThread.java
package com.myapp;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class ViewThread extends Thread {
private Panel mPanel;
private SurfaceHolder mHolder;
private boolean mRun = false;
private long mStartTime;
private long mElapsed;
public ViewThread(Panel panel) {
mPanel = panel;
mHolder = mPanel.getHolder();
}
public void setRunning(boolean run) {
mRun = run;
}
@Override
public void run() {
Canvas canvas = null;
mStartTime = System.currentTimeMillis();
while (mRun) {
canvas = mHolder.lockCanvas();
if (canvas != null) {
mPanel.doDraw(mElapsed, canvas);
mElapsed = System.currentTimeMillis() - mStartTime;
mHolder.unlockCanvasAndPost(canvas);
}
mStartTime = System.currentTimeMillis();
}
}
}
MainActivity.java
package com.myapp;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// *** from Surface Page
Intent intent= getIntent();
final String fileNamePath = intent.getStringExtra("fileName"); // for get FileName
ImageView imageView = (ImageView) findViewById(R.id.imageShot);
if(fileNamePath != null)
{
Bitmap bm = BitmapFactory.decodeFile(fileNamePath);
imageView.setImageBitmap(bm);
}
else
{
imageView.setImageResource(android.R.drawable.sym_def_app_icon);
}
// btnTakePhoto
final Button btnTakePhoto = (Button) findViewById(R.id.btnTakePhoto);
// Perform action on click
btnTakePhoto.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent newActivity = new Intent(MainActivity.this,TakePhotoActivity.class);
startActivity(newActivity);
}
});
}
}
TakePhotoActivity.java
package com.myapp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
public class TakePhotoActivity extends Activity {
private Panel mPanel;
String fileNamePath;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
fileNamePath = Environment.getExternalStorageDirectory()
+ "/picture" + "/" + System.currentTimeMillis() + ".jpg";
mPanel = new Panel(this,fileNamePath);
setContentView(mPanel);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.screenshot:
mPanel.saveScreenshot();
mPanel.CloseSurface();
Intent newActivity1 = new Intent(TakePhotoActivity.this,MainActivity.class);
newActivity1.putExtra("fileName", fileNamePath);
startActivity(newActivity1);
break;
case R.id.cancel:
mPanel.CloseSurface();
Intent newActivity2 = new Intent(TakePhotoActivity.this,MainActivity.class);
startActivity(newActivity2);
break;
}
return true;
}
}
เพิ่มเติม
fileNamePath = Environment.getExternalStorageDirectory()
+ "/picture" + "/" + System.currentTimeMillis() + ".jpg";
จาก Code จะเป็นการ Save ลงในโฟเดอร์ /mnt/sdcard/picture/ เพระาฉะนั้นจะต้องตรวจสอบด้วยว่ามีโฟเดอร์อยู่จริง ๆ หรือไม่
เพิ่ม TakePhotoActivity ลงในไฟล์ AndroidManifest.xml
AndroidManifest.xml
<activity
android:name=".TakePhotoActivity"
android:theme="@style/AppTheme"
android:screenOrientation="portrait"
android:label="@string/title_activity_main" />
Screenshot
เนื่องจากเป็นการทดสอบผ่าน Emulator และการทดสอบการ จะไม่เห็นภาพ แต่จะเห็นเป็นภาพดำ ๆ แต่เมื่อนำไปใช้งานจริง จะสามารถใช้งานได้ตามปกติ
หน้าจอแรกของ Application ซึ่งตอนนี้จะแสดงภาพ Default เป็น Icons ของ Logo ของ Android ให้คลิกที่ Take Photo
จะสดงมุมมองของกล้อง Camera ในกรณีที่ต้องการ Save Screen ให้คลิกที่เมูบน Emulator
เลือก Save Screenshot เพื่อบันทึกภาพปัจจุบัน
จะได้ภาพซึ่งจะถูกบันทึกลงใน SD Card และสามารถนำภาพมาแสดงบน ImageView
ไฟล์ถูกสร้างลงใน SD Card บน Emulator หรือ Smartphone
.
|
ช่วยกันสนับสนุนรักษาเว็บไซต์ความรู้แห่งนี้ไว้ด้วยการสนับสนุน Source Code 2.0 ของทีมงานไทยครีเอท
|
|
|
By : |
ThaiCreate.Com Team (บทความเป็นลิขสิทธิ์ของเว็บไทยครีเอทห้ามนำเผยแพร่ ณ เว็บไซต์อื่น ๆ) |
|
Score Rating : |
|
|
|
Create/Update Date : |
2012-09-08 11:43:39 /
2017-03-26 22:35:08 |
|
Download : |
|
|
Sponsored Links / Related |
|
|
|
|
|
|
|