創建GrayFun的class類別
GrayFun.java
package com.example.cheng.gray;
/**
* Created by Cheng on 2016/12/4.
*/
public class GrayFun {
static {
System.loadLibrary("GrayFun");
}
public static native int[] GrayFun(int[] buf, int w, int h);
}
package com.example.cheng.gray;
/**
* Created by Cheng on 2016/12/4.
*/
public class GrayFun {
static {
System.loadLibrary("GrayFun");
}
public static native int[] GrayFun(int[] buf, int w, int h);
}
import android.support.v7.app.AppCompatActivity;.xml
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView infoText = (TextView)findViewById(R.id.text_libinfo);
infoText.setMovementMethod(ScrollingMovementMethod.getInstance());
Button button = (Button)this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
infoText.setText(avcodecinfo());
}
});
}
//JNI
public native String avcodecinfo();
static{
System.loadLibrary("avutil-55");
System.loadLibrary("swresample-2");
System.loadLibrary("avcodec-57");
System.loadLibrary("avformat-57");
System.loadLibrary("swscale-4");
System.loadLibrary("avfilter-6");
System.loadLibrary("sffhelloworld");
}
}
<?xml version="1.0" encoding="utf-8"?>接著再使用JDK提供的「javah」工具,來將指定類別轉換成JNI使用的標頭檔
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.cheng.myapplication.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="@+id/textView" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_alignParentStart="true"
android:layout_marginTop="122dp"
android:id="@+id/text_libinfo" />
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_alignParentStart="true"
android:layout_marginTop="13dp"
android:id="@+id/button" />
</RelativeLayout>
//Android.mk
// Created by cheng on 2016/11/29.
//
#include "com_example_cheng_myapplication_MainActivity.h"
#include <stdio.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#ifdef ANDROID
#include <jni.h>
#include <android/log.h>
#define LOGE(format, ...) __android_log_print(ANDROID_LOG_ERROR, "(>_<)", format, ##__VA_ARGS__)
#else
#define LOGE(format, ...) printf("(>_<) " format "\n", ##__VA_ARGS__)
#endif
JNIEXPORT jstring Java_com_example_cheng_myapplication_MainActivity_avcodecinfo(JNIEnv *env, jobject obj){
char info[40000]={0};
av_register_all();
AVCodec *c_temp = av_codec_next(NULL);
while (c_temp != NULL){
if(c_temp != NULL){
sprintf(info, "%s[Dec]\n", info);
}else{
sprintf(info, "%s[Enc]\n", info);
}
switch(c_temp->type){
case AVMEDIA_TYPE_VIDEO:
sprintf(info, "%s[Video]\n", info);
break;
case AVMEDIA_TYPE_AUDIO:
sprintf(info, "%s[Audio]\n", info);
break;
default:
sprintf(info, "%s[Other]\n", info);
break;
}
sprintf(info, "%s[%10s]\n", info,c_temp->name);
c_temp = c_temp->next;
}
return (*env).NewStringUTF(info);
}
LOCAL_PATH := $(call my-dir)LOCAL_MODULE = "xxxx"就是System.loadLibrary的名子
# FFmpeg library
include $(CLEAR_VARS)
LOCAL_MODULE := avcodec
LOCAL_SRC_FILES := libavcodec-57.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avfilter
LOCAL_SRC_FILES := libavfilter-6.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avformat
LOCAL_SRC_FILES := libavformat-57.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avutil
LOCAL_SRC_FILES := libavutil-55.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swresample
LOCAL_SRC_FILES := libswresample-2.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swscale
LOCAL_SRC_FILES := libswscale-4.so
include $(PREBUILT_SHARED_LIBRARY)
# Program
include $(CLEAR_VARS)
LOCAL_MODULE := libsffhelloworld
LOCAL_SRC_FILES := simplest_ffmpeg_helloworld.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_LDLIBS := -llog -lz
LOCAL_SHARED_LIBRARIES := avcodec avdevice avfilter avformat avutil postproc swresample swscale
include $(BUILD_SHARED_LIBRARY)
APP_ABI := armeabi開始編譯目標so,在Studio中的Terminal面板中:執行ndk-build (在此之前記得要在local.properties下配置ndk目錄)
defaultConfig {
applicationId "com.example.cheng.myapplication"
minSdkVersion 19
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk{
moduleName "libsffhelloworld"
}
sourceSets.main{
jni.srcDirs=[]
jniLibs.srcDir "src/main/jniLibs"
}
}
在gradle.properties android.useDeprecatedNdk=true
#define __STDC_CONSTANT_MACROS
#define inline __inline
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#endif
http://blog.csdn.net/hejjunlin/article/details/52661331
https://magiclen.org/android-jni/
http://jojosula001.pixnet.net/blog/post/173475381-%5Bwindows%5D-using-ffmpeg-in-visual-c%2B%2B
https://github.com/dxjia/ffmpeg-compile-shared-library-for-android
http://blog.csdn.net/leixiaohua1020/article/details/47008825
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
#!/bin/bash
NDK=/home/cheng/Android/android-ndk-r13b
SYSROOT=$NDK/platforms/android-9/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-doc \
--disable-symver \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one
sudo chmod +x build_android.sh開始編譯喝杯咖啡等個10~20分鐘吧
http://blog.csdn.net/leixiaohua1020/article/details/47008825
http://www.jianshu.com/p/313f378f9922
http://blog.csdn.net/hejjunlin/article/details/52661331
http://www.itread01.com/articles/1475294828.html
<?xml version="1.0" encoding="utf-8"?>在文件夾src下的com.XXX.haveimgfun包中新建一個類用於包裝使用了opencv c++代碼的動態庫的導出函數,類名為LibImgFun。 Android Studio會為你創建一個新的文件LibImgFun.java,將裡面的內容改為:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:id="@+id/btnNDK"
android:text="使用C++ OpenCV进行处理" />
<Button android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:id="@+id/btnRestore"
android:text="还原" />
<TextView
android:text="TextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView2" />
<ImageView android:id="@+id/ImageView01"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
package com.example.cheng.haveimgfun;從上面的代碼可以得知,我們的動態庫名字應該為“libImgFun.so”。
/**
* Created by Cheng on 2016/11/23.
*/
public class LibImgFun {
static {
System.loadLibrary("ImgFun");
}
public static native int[] ImgFun(int[] buf, int w, int h);
public native String getMycstring();
}
//
// Created by Cheng on 2016/11/23.
//
//
// Created by Cheng on 2016/11/23.
//
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/opencv.hpp>
#include "com_example_cheng_haveimgfun_LibImgFun.h"
JNIEXPORT jstring JNICALL Java_com_example_cheng_haveimgfun_LibImgFun_getMycstring
(JNIEnv * evn, jobject obj) {
return ( * evn).NewStringUTF("Hello NKD demo");
}
using namespace cv;
IplImage * change4channelTo3InIplImage(IplImage * src);
extern "C" {
JNIEXPORT jintArray JNICALL Java_com_example_cheng_haveimgfun_LibImgFun_ImgFun
(JNIEnv * env, jobject obj, jintArray buf, jint w, jint h) {
jint * cbuf;
cbuf = env - > GetIntArrayElements(buf, NULL);
printf("%d",cbuf);
if (cbuf == NULL) {
return 0;
}
Mat myimg(h, w, CV_8UC4, (unsigned char * ) cbuf);
IplImage image = IplImage(myimg);
IplImage * image3channel = change4channelTo3InIplImage( & image);
IplImage * pCannyImage = cvCreateImage(cvGetSize(image3channel), IPL_DEPTH_8U, 1);
cvCanny(image3channel, pCannyImage, 50, 150, 3);
int * outImage = new int[w * h];
for (int i = 0; i < w * h; i++) {
outImage[i] = (int) pCannyImage - > imageData[i];
}
int size = w * h;
jintArray result = env - > NewIntArray(size);
env - > SetIntArrayRegion(result, 0, size, outImage);
env - > ReleaseIntArrayElements(buf, cbuf, 0);
return result;
}
}
IplImage * change4channelTo3InIplImage(IplImage * src) {
if (src - > nChannels != 4) {
return NULL;
}
IplImage * destImg = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);
for (int row = 0; row < src - > height; row++) {
for (int col = 0; col < src - > width; col++) {
CvScalar s = cvGet2D(src, row, col);
cvSet2D(destImg, row, col, s);
}
}
return destImg;
}
LOCAL_PATH := $(call my-dir)在Android.mk文件中,需要主要修改的代碼是如下一行:
include $(CLEAR_VARS)
OPENCV_LIB_TYPE:=STATIC
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
#try to load OpenCV.mk from default install location
include D:\OpenCV-android-sdk\sdk\native\jni\OpenCV.mk
else
include $(OPENCV_MK_PATH)
endif
LOCAL_MODULE := ImgFun
LOCAL_SRC_FILES := ImgFun.cpp
include $(BUILD_SHARED_LIBRARY)
include D:\OpenCV-android-sdk\sdk\native\jni\OpenCV.mk
APP_STL:=gnustl_staticReference:
APP_CPPFLAGS:=-frtti -fexceptions
APP_ABI := all
http://blog.csdn.net/watkinsong/article/details/8829235
http://blog.csdn.net/watkinsong/article/details/9849973
安裝環境
$JDKPath$/bin/javah.exe
-v -jni -d $ModuleFileDir$/src/main/jni $FileClass$
$SourcepathEntry$
簡單解說: $JDKPath$是環境變數,該行會自動取得你電腦裡面JDK的javah檔案路徑 D:\android-ndk-r10e\ndk-build.cmd
NDK_PROJECT_PATH=$ModuleFileDir$/build/intermediates/ndk
NDK_LIBS_OUT=$ModuleFileDir$/src/main/jniLibs
NDK_APPLICATION_MK=$ModuleFileDir$/src/main/jni/Application.mk
APP_BUILD_SCRIPT=$ModuleFileDir$/src/main/jni/Android.mk V=1
$ProjectFileDir$
簡單解說:ndk{
moduleName "myJNI"
}
sourceSets.main{
jni.srcDirs=[]
jniLibs.srcDir "src/main/jniLibs"
}
解說:
android.useDeprecatedNdk=true
static {
System.loadLibrary("myJNI");
}
public native String getMycstring();
解說://
// Created by Cheng on 2016/11/22.
//
#include"com_example_cheng_testndk_myNDK.h"
JNIEXPORT jstring JNICALL Java_com_example_cheng_testndk_myNDK_getMycstring
(JNIEnv * evn, jobject obj)
{
return (*evn).NewStringUTF("Hello NKD demo");
}
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := myJNI
LOCAL_SRC_FILES := myJNI.cpp
include $(BUILD_SHARED_LIBRARY)
快速複製區APP_ABI := all
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textTX=(TextView)findViewById(R.id.textTX);
TextView textView3 = (TextView)findViewById(R.id.textView3);
myNDK testNDK=new myNDK();
int a = testNDK.getMyint();
textTX.setText(testNDK.getMycstring());
String s = Integer.toString(a);
textView3.setText(s);
}
}
Reference: http://blog.xuite.net/lwchafter30/blog/373974237-Android+studio+1.5.1+NDK+JNI%E7%92%B0%E5%A2%83%E5%AE%89%E8%A3%9D%E8%88%87%E5%9F%B7%E8%A1%8C%E5%8E%9F%E7%90%86
https://www.youtube.com/watch?v=RmPuwdxR1qs
https://wl9739.github.io/2016/09/21/%E5%9C%A8-Android-Studio-2-2-%E4%B8%AD%E6%84%89%E5%BF%AB%E5%9C%B0%E4%BD%BF%E7%94%A8-C-C-md/
https://developer.android.com/studio/projects/add-native-code.html#download-ndk
https://developer.android.com/studio/projects/create-project.html
xxx.java
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.cheng.myapplication.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="OpenCV"/>
<ImageView
android:id="@+id/img"
android:layout_width="700px"
android:layout_height="700px"
android:background="@drawable/lena"
android:layout_centerHorizontal="true" />
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/img"
android:layout_centerHorizontal="true"
android:text="灰度化"/>"
"
</RelativeLayout>
package org.opencv.android;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.util.Log;
/**
* Basic implementation of LoaderCallbackInterface.
*/
public abstract class BaseLoaderCallback implements LoaderCallbackInterface {
public BaseLoaderCallback(Context AppContext) {
mAppContext = AppContext;
}
public void onManagerConnected(int status)
{
switch (status)
{
/** OpenCV initialization was successful. **/
case LoaderCallbackInterface.SUCCESS:
{
/** Application must override this method to handle successful library initialization. **/
} break;
/** OpenCV loader can not start Google Play Market. **/
case LoaderCallbackInterface.MARKET_ERROR:
{
Log.e(TAG, "Package installation failed!");
AlertDialog MarketErrorMessage = new AlertDialog.Builder(mAppContext).create();
MarketErrorMessage.setTitle("OpenCV Manager");
MarketErrorMessage.setMessage("Package installation failed!");
MarketErrorMessage.setCancelable(false); // This blocks the 'BACK' button
MarketErrorMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
MarketErrorMessage.show();
} break;
/** Package installation has been canceled. **/
case LoaderCallbackInterface.INSTALL_CANCELED:
{
Log.d(TAG, "OpenCV library instalation was canceled by user");
finish();
} break;
/** Application is incompatible with this version of OpenCV Manager. Possibly, a service update is required. **/
case LoaderCallbackInterface.INCOMPATIBLE_MANAGER_VERSION:
{
Log.d(TAG, "OpenCV Manager Service is uncompatible with this app!");
AlertDialog IncomatibilityMessage = new AlertDialog.Builder(mAppContext).create();
IncomatibilityMessage.setTitle("OpenCV Manager");
IncomatibilityMessage.setMessage("OpenCV Manager service is incompatible with this app. Try to update it via Google Play.");
IncomatibilityMessage.setCancelable(false); // This blocks the 'BACK' button
IncomatibilityMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
IncomatibilityMessage.show();
} break;
/** Other status, i.e. INIT_FAILED. **/
default:
{
Log.e(TAG, "OpenCV loading failed!");
AlertDialog InitFailedDialog = new AlertDialog.Builder(mAppContext).create();
InitFailedDialog.setTitle("OpenCV error");
InitFailedDialog.setMessage("OpenCV was not initialised correctly. Application will be shut down");
InitFailedDialog.setCancelable(false); // This blocks the 'BACK' button
InitFailedDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
InitFailedDialog.show();
} break;
}
}
public void onPackageInstall(final int operation, final InstallCallbackInterface callback)
{
switch (operation)
{
case InstallCallbackInterface.NEW_INSTALLATION:
{
AlertDialog InstallMessage = new AlertDialog.Builder(mAppContext).create();
InstallMessage.setTitle("Package not found");
InstallMessage.setMessage(callback.getPackageName() + " package was not found! Try to install it?");
InstallMessage.setCancelable(false); // This blocks the 'BACK' button
InstallMessage.setButton(AlertDialog.BUTTON_POSITIVE, "Yes", new OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
callback.install();
}
});
InstallMessage.setButton(AlertDialog.BUTTON_NEGATIVE, "No", new OnClickListener() {
public void onClick(DialogInterface dialog, int which)
{
callback.cancel();
}
});
InstallMessage.show();
} break;
case InstallCallbackInterface.INSTALLATION_PROGRESS:
{
AlertDialog WaitMessage = new AlertDialog.Builder(mAppContext).create();
WaitMessage.setTitle("OpenCV is not ready");
WaitMessage.setMessage("Installation is in progress. Wait or exit?");
WaitMessage.setCancelable(false); // This blocks the 'BACK' button
WaitMessage.setButton(AlertDialog.BUTTON_POSITIVE, "Wait", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
callback.wait_install();
}
});
WaitMessage.setButton(AlertDialog.BUTTON_NEGATIVE, "Exit", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
callback.cancel();
}
});
WaitMessage.show();
} break;
}
}
void finish()
{
((Activity) mAppContext).finish();
}
protected Context mAppContext;
private final static String TAG = "OpenCVLoader/BaseLoaderCallback";
}
http://stackoverflow.com/questions/27406303/opencv-in-android-studio
http://blog.csdn.net/gao_chun/article/details/49359535
https://github.com/jlhonora/opencv-android-sample
<uses-permission android:name="android.permission.CAMERA" />為了拍照這個類,使用下面的步驟:
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
package com.example.cheng.camera_for_led;最後提醒的是,如果程序中加入了previewCallback,在surfaceDestroy釋放camera的時候,最好執行myCamera.setOneShotPreviewCallback(null); 或者myCamera.setPreviewCallback(null); 中止這種回調,然後再釋放camera更安全。否則可能會報錯。 Reference:
import android.app.Activity;
import android.content.Intent;
import android.hardware.Camera;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import static android.hardware.Camera.getNumberOfCameras;
public class MainActivity extends Activity implements SurfaceHolder.Callback {
private static final String TAG = "My_CAMERA";
Camera myCamera;
Button button1;
SurfaceView previewSurfaceView;
SurfaceHolder previewSurfaceHolder;
boolean previewing = false;
// 视频数据
private StreamIt streamIt = null;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().setFormat(PixelFormat.UNKNOWN);
previewSurfaceView = (SurfaceView) findViewById(R.id.previewsurface);
previewSurfaceHolder = previewSurfaceView.getHolder();// 绑定SurfaceView,取得SurfaceHolder对象
previewSurfaceHolder.addCallback(this);//SurfaceHolder加入回调接口
previewSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// 設置顯示器類型,setType必须设置
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
myCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
});
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
Camera.Parameters parameters = myCamera.getParameters();//獲取Camera.Parameters的實例
myCamera.startPreview();
Log.d(TAG, format + "+" + width + "+" + height);
//Camera Focus mode 必須透過 setParameters() 設定,自動對焦則有三種模式
List<String> allFocus = parameters.getSupportedFocusModes();
if (allFocus.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);//设置聚焦模式
} else if (allFocus.contains(Camera.Parameters.FLASH_MODE_AUTO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);//设置聚焦模式
}
streamIt = new StreamIt();
myCamera.setDisplayOrientation(90);//螢幕轉向90度
myCamera.setPreviewCallback(streamIt);
myCamera.setParameters(parameters);// 设置Camera parameters
myCamera.startPreview();//開始捕獲並顯示幀
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
if (previewing) {//如果硬體沒有相機
myCamera.stopPreview();//停止相機功能
previewing = false;
}
myCamera = Camera.open();//開啟鏡頭(2.3版本后支持多摄像头,需传入参数)
int a = getNumberOfCameras();
Log.d(TAG + " number = ", String.valueOf(a));//硬體鏡頭可用數
try {///設置surface用來顯示實時的預覽
myCamera.setPreviewDisplay(holder);
Log.d(TAG, "start");
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
myCamera.stopPreview();//停止相机功能
myCamera.release();
myCamera = null;
previewing = false;
}
class StreamIt implements Camera.PreviewCallback {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
Log.i(TAG, "执行了capture方法");
}
}
private void resetCam() {
myCamera.startPreview();
// parameters.setCamera(myCamera);
}
private void refreshGallery(File file) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(Uri.fromFile(file));
sendBroadcast(mediaScanIntent);
}
Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() {
public void onShutter() {
Log.d(TAG, "onShutter'd");
}
};
Camera.PictureCallback rawCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
Log.d(TAG, "onPictureTaken - raw");
}
};
Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
new SaveImageTask().execute(data);
resetCam();
Log.d(TAG, "onPictureTaken - jpeg");
}
};
private class SaveImageTask extends AsyncTask<byte[], Void, Void> {
@Override
protected Void doInBackground(byte[]... data) {
FileOutputStream outStream = null;
// Write to SD Card
try {
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard.getAbsolutePath() + "/camtest");
dir.mkdirs();
String fileName = String.format("%d.jpg", System.currentTimeMillis());
File outFile = new File(dir, fileName);
outStream = new FileOutputStream(outFile);
outStream.write(data[0]);
outStream.flush();
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length + " to " + outFile.getAbsolutePath());
refreshGallery(outFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
return null;
}
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "执行了onStart方法");
}
//Activity从后台重新回到前台时被调用
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, "执行了onRestart方法");
}
//Activity创建或者从被覆盖、后台重新回到前台时被调用
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "执行了onResume方法");
}
//Activity被覆盖到下面或者锁屏时被调用
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "执行了onPause方法");
}
//退出当前Activity或者跳转到新Activity时被调用
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "执行了onStop方法");
}
//退出当前Activity时被调用,调用之后Activity就结束了
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "执行了onDestroy方法");
}
}
https://developer.android.com/reference/android/hardware/Camera.html#takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback)
https://developer.android.com/reference/android/hardware/Camera.html#getParameters()
https://developer.android.com/reference/android/hardware/Camera.html
https://github.com/josnidhin/Android-Camera-Example/blob/master/src/com/example/cam/CamTestActivity.java
http://fecbob.pixnet.net/blog/post/36606464-android-%E6%8B%8D%E7%85%A7api%E6%B5%81%E7%A8%8B