2015-11-28 16:01:13 u012796139 阅读数 1875
  • Android底层技术:HAL驱动开发

    本课程提供开发者学习Android底层的HAL(硬件抽象层)的开发方法和技术。HAL所在的位置是介于Android系统服务与Linux内核之间,HAL Driver是以library形式出现,给HAL Stub调用,供Android System架构者调用。而HAL Stub则是google设计出来的,保护硬件厂商的硬件驱动。

    17829 人正在学习 去看看 高煥堂

        Android调用摄像头是很方便的。先看一下界面



布局文件activity_main.xml源码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/take_photo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="启动相机" />

    <Button
        android:id="@+id/choose_from_album"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="从相册中选择图片" />

    <ImageView
        android:id="@+id/picture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

</LinearLayout>


因为涉及到向SD卡写入数据,所有需要在AndroidMainfest.xml中声明响应权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

MainActivity.java源码

package com.example.luoxn28.activity;

import android.annotation.TargetApi;
import android.content.ContentUris;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class MainActivity extends ActionBarActivity {
    private static final String TAG = "hdu";

    public static final int TAKE_PHOTO = 1;
    public static final int CROP_PHOTO = 2;
    public static final int CHOOSE_PHOTO = 3;

    private Button takePhoto;
    private ImageView picture;
    private Uri imageUri;

    private Button chooseFromAlbum;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);

        takePhoto = (Button) findViewById(R.id.take_photo);
        picture = (ImageView) findViewById(R.id.picture);
        chooseFromAlbum = (Button) findViewById(R.id.choose_from_album);

        takePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 创建File对象,用于存储拍摄后照片
                File saveImage = new File(Environment.getExternalStorageDirectory(), "saveImage.jpg");
                try {
                    if (saveImage.exists()) {
                        saveImage.delete();
                    }
                    saveImage.createNewFile();
                }
                catch (IOException ex) {
                    ex.printStackTrace();
                }

                imageUri = Uri.fromFile(saveImage);
                Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
                intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                // 启动相机
                startActivityForResult(intent, TAKE_PHOTO);
            }
        });

        chooseFromAlbum.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("android.intent.action.GET_CONTENT");
                intent.setType("image/*");
                // 打开相册
                startActivityForResult(intent, CHOOSE_PHOTO);
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case TAKE_PHOTO:
                if (resultCode == RESULT_OK) {
                    Intent intent = new Intent("com.android.camera.action.CROP");
                    intent.setDataAndType(imageUri, "image/*");
                    intent.putExtra("scale", true);
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                    // 启动裁剪程序
                    startActivityForResult(intent, CROP_PHOTO);
                }
                break;

            case CROP_PHOTO:
                if (resultCode == RESULT_OK) {
                    try {
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
                        // 显示裁剪后的图片
                        picture.setImageBitmap(bitmap);
                    }
                    catch (FileNotFoundException ex) {
                        ex.printStackTrace();
                    }
                }
                break;

            case CHOOSE_PHOTO:
                if (resultCode == RESULT_OK) {
                    handleImage(data);
                }
                break;

            default:
                break;
        }
    }

    // 只在Android4.4及以上版本使用
    @TargetApi(19)
    private void handleImage(Intent data) {
        String imagePath = null;
        Uri uri = data.getData();

        if (DocumentsContract.isDocumentUri(this, uri)) {
            // 通过document id来处理
            String docId = DocumentsContract.getDocumentId(uri);
            if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                // 解析出数字id
                String id = docId.split(":")[1];
                String selection = MediaStore.Images.Media._ID + "=" + id;
                imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
            }
            else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),
                        Long.valueOf(docId));
                imagePath = getImagePath(contentUri, null);
            }
        }
        else if ("content".equals(uri.getScheme())) {
            // 如果不是document类型的Uri,则使用普通方式处理
            imagePath = getImagePath(uri, null);
        }

        // 根据图片路径显示图片
        displayImage(imagePath);
    }

    private String getImagePath(Uri uri, String selection) {
        String path = null;
        // 通过Uri和selection来获取真实图片路径
        Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
            }
            cursor.close();
        }

        return path;
    }

    private void displayImage(String imagePath) {
        if (imagePath != null) {
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            picture.setImageBitmap(bitmap);
        }
        else {
            Toast.makeText(this, "failed to get image", Toast.LENGTH_SHORT).show();
        }
    }
}


调用摄像头拍照

        在 MainActivity 中要做的第一件事自然是分别获取到 Button 和 ImageView 的实例,并给 Button 注册上点击事件,然后在 Button的点击事件里开始处理调用摄像头的逻辑,我们重点看下这部分代码。

        首先这里创建了一个 File 对象,用于存储摄像头拍下的图片,这里我们把图片命名为saveImage.jpg ,并将它存放在手机SD卡的根目录下,调 用 Environment 的getExternalStorageDirectory()方法获取到的就是手机 SD 卡的根目录。然后再调用 Uri 的fromFile()方法将 File 对象转换成 Uri 对象,这个 Uri 对象标识着 saveImage.jpg 这张图片的唯一地址。 接着构建出一个 Intent对象, 并将这个 Intent的 action指定为android.media.action.IMAGE_CAPTURE,再调用 Intent 的 putExtra()方法指定图片的输出地址,这里填入刚刚得到的 Uri 对象,最后调用 startActivityForResult()来启动活动。由于我们使用的是一个隐式Intent,系统会找出能够响应这个 Intent 的活动去启动,这样照相机程序就会被打开,拍下的照片将会输出到 saveImage.jpg 中。

        注意刚才我们是使用 startActivityForResult()来启动活动的,因此拍完照后会有结果返回到 onActivityResult()方法中。如果发现拍照成功,则会再次构建出一个 Intent 对象,并把它的 action 指定为 com.android.camera.action.CROP。这个 Intent 是用于对拍出的照片进行裁剪注意刚才我们是使用 startActivityForResult()来启动活动的,因此拍完照后会有结果返回到 onActivityResult()方法中。如果发现拍照成功,则会再次构建出一个 Intent 对象,并把它的 action 指定为 com.android.camera.action.CROP。这个 Intent 是用于对拍出的照片进行裁剪

从相册中选择照片

        在 "从相册中选择图片"按钮的点击事件里我们同样创建了一个 File 对象,用于存储从相册中选择的图片。然后构建出一个 Intent 对象,并将它的 action 指定为android.intent.action.GET_CONTENT。接着给这个 Intent 对象设置一些必要的参数,包括是否允许缩放和裁剪、图片的输出位置等。最后调用 startActivityForResult()方法,就可以打开相册程序选择照片了。

        注意在调用 startActivityForResult()方法的时候,我们给第二个参数传入的值仍然是CROP_PHOTO 常量,这样的好处就是从相册选择好照片之后,会直接进入到 CROP_PHOTO的 case 下将图片显示出来, 这样就可以复用之前写好的显示图片的逻辑, 不用再编写一遍了。


参考资料

        1、《第一行代码-Android》调用摄像头章节


2017-05-23 19:41:01 xiaoLP1 阅读数 1260
  • Android底层技术:HAL驱动开发

    本课程提供开发者学习Android底层的HAL(硬件抽象层)的开发方法和技术。HAL所在的位置是介于Android系统服务与Linux内核之间,HAL Driver是以library形式出现,给HAL Stub调用,供Android System架构者调用。而HAL Stub则是google设计出来的,保护硬件厂商的硬件驱动。

    17829 人正在学习 去看看 高煥堂

Android调用摄像头拍照和从相册中选择(上传、更换头像)

1.布局文件里写两个按钮一个为拍照一个为从相册中选择,还有一个ImageVIew用来放头像

<LinearLayout 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"
  android:orientation="vertical"
    tools:context="com.example.choosepictest.MainActivity" >

    <Button
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="拍照"
      android:id="@+id/but1"
      />
      <Button
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="从相册中选择"
      android:id="@+id/but2"
      />
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/img"
        />

</LinearLayout>

2.MainActivity中直接贴代码


package com.example.choosepictest;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.ContactsContract.Contacts.Data;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.Media;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {
public static final int TAKE_PHOTO=1;
public static final int CROP_PHOTO=2;
private Button takephoto;
private ImageView picture;
private Uri imageUri;

public static final int CHOOSE_PHOTO=3;
private Button choose;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  takephoto=(Button) findViewById(R.id.but1);
  picture=(ImageView) findViewById(R.id.img);
  choose=(Button) findViewById(R.id.but2);
  takephoto.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View arg0) {
    // TODO Auto-generated method stub
    File outputImage=new File(Environment.getExternalStorageDirectory(),
       "output_image.jpg");
   
    try {
     if (outputImage.exists()) {
      outputImage.delete();
     }
     outputImage.createNewFile();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    imageUri=Uri.fromFile(outputImage);
    Intent intent=new Intent("android.media.action.IMAGE_CAPTURE");
    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    startActivityForResult(intent, TAKE_PHOTO);
   }
  });
  
  choose.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View arg0) {
    // TODO Auto-generated method stub
    Intent intent=new Intent("android.intent.action.GET_CONTENT");
    intent.setType("image/*");
    startActivityForResult(intent, CHOOSE_PHOTO);
   }
  });
 }
@Override
 protected void onActivityResult(int arg0, int arg1, Intent arg2) {
  // TODO Auto-generated method stub
  super.onActivityResult(arg0, arg1, arg2);
  switch (arg0) {
  case TAKE_PHOTO:
   if (arg1==RESULT_OK) {
    Intent intent=new Intent("com.android.camera.action.CROP");
    intent.setDataAndType(imageUri, "image/*");
    intent.putExtra("scale", true);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    startActivityForResult(intent, CROP_PHOTO);
    
   }
   break;
  case CROP_PHOTO:
   if (arg1==RESULT_OK) {
    Bitmap bitmap;
    try {
     bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
     picture.setImageBitmap(bitmap);

    } catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   break;
   
  case CHOOSE_PHOTO:
   if (arg1==RESULT_OK) {
    if (Build.VERSION.SDK_INT>=19) {
     handleImageOnKitKat(arg2);
     
    }else{
     handleImageBeforeKitKat(arg2);
    }
   }
   break;
  default:
   break;
  }
 }
 
@SuppressLint("NewApi")
private void handleImageOnKitKat(Intent data) {
 // TODO Auto-generated method stub
String imagePath=null;
Uri uri=data.getData();
if (DocumentsContract.isDocumentUri(this, uri)) {
 String docId=DocumentsContract.getDocumentId(uri);
 if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
  String id=docId.split(":")[1];//解析数字格式的ID
  String selection=MediaStore.Images.Media._ID+"="+id;
  imagePath=getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection);
  
  
 }else if("com.android.providers.downloads.documents".equals(uri.getAuthority())){
  Uri contentUri=ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
  imagePath=getImagePath(contentUri, null);
  
  
 }
 
}else if("content".equalsIgnoreCase(uri.getScheme())){
 imagePath=getImagePath(uri, null);
 
}
displayImage(imagePath);
}
private void handleImageBeforeKitKat(Intent data){
 Uri uri=data.getData();
 String imagePath=getImagePath(uri, null);
 displayImage(imagePath);
}
private String getImagePath(Uri uri,String selection) {
 // TODO Auto-generated method stub
 String path=null;
 Cursor cursor=getContentResolver().query(uri, null, selection, null, null);
 if (cursor!=null) {
  if (cursor.moveToFirst()) {
   path=cursor.getString(cursor.getColumnIndex(Media.DATA));
   
   
  }
  cursor.close();
 }
 return path;
}
private void displayImage(String imagePath) {
 // TODO Auto-generated method stub
 if (imagePath!=null) {
  Bitmap bitmap=BitmapFactory.decodeFile(imagePath);
  picture.setImageBitmap(bitmap);
  
 }else{
  Toast.makeText(this, "failed to get image", 0).show();
 }
}
}


3.加上权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


具体项目代码见本人博客资源

2018-08-14 11:54:33 qq_41901915 阅读数 6809
  • Android底层技术:HAL驱动开发

    本课程提供开发者学习Android底层的HAL(硬件抽象层)的开发方法和技术。HAL所在的位置是介于Android系统服务与Linux内核之间,HAL Driver是以library形式出现,给HAL Stub调用,供Android System架构者调用。而HAL Stub则是google设计出来的,保护硬件厂商的硬件驱动。

    17829 人正在学习 去看看 高煥堂

演示代码的功能,调用摄像头拍照,成功的话则把照片显示出来。

第一步 定义一个按钮用于调用摄像头拍照,ImageView用于存放显示拍出的照片。

<Button
        android:id="@+id/take_photo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="take photo"
        />
    <ImageView
        android:id="@+id/picture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        />

第二步 开始编写调用摄像头的具体逻辑

package example.com.test;
//逻辑,先创建文件,之后把它封装成uri对象,之后封装带intent中,调用摄像头,之后调用过后会有一个
//返回结果,成功的话就把它显示出来
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
    public static final int TAKE_PHOTO=1;//声明一个请求码,用于识别返回的结果
    private ImageView picture;
    private Uri imageUri;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button takephoto=findViewById(R.id.take_photo);
        picture=findViewById(R.id.picture);
        takephoto.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                File outputImage=new File(getExternalCacheDir(),"output_image.jpg");
                /*
                创建一个File文件对象,用于存放摄像头拍下的图片,我们把这个图片命名为output_image.jpg
                并把它存放在应用关联缓存目录下,调用getExternalCacheDir()可以得到这个目录,为什么要
                用关联缓存目录呢?由于android6.0开始,读写sd卡列为了危险权限,使用的时候必须要有权限,
                应用关联目录则可以跳过这一步
                 */
                try//判断图片是否存在,存在则删除在创建,不存在则直接创建
                {
                    if(outputImage.exists())
                    {
                        outputImage.delete();
                    }
                    outputImage.createNewFile();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
                if(Build.VERSION.SDK_INT>=24)
                    //判断安卓的版本是否高于7.0,高于则调用高于的方法,低于则调用低于的方法
                    //把文件转换成Uri对象
                    /*
                    之所以这样,是因为android7.0以后直接使用本地真实路径是不安全的,会抛出异常。
                    FileProvider是一种特殊的内容提供器,可以对数据进行保护
                     */
                {
                    imageUri= FileProvider.getUriForFile(MainActivity.this,
                            "com.example.cameraalbumtest.fileprovider",outputImage);
                    /*
                    第一个参数:context对象
                    第二个参数:任意唯一的字符串
                    第三个参数:文件对象
                     */

                }
                else {
                    imageUri=Uri.fromFile(outputImage);
                }
                //使用隐示的Intent,系统会找到与它对应的活动,即调用摄像头,并把它存储
                Intent intent=new intent("android.media.action.IMAGE_CAPTURE");
                intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
                startActivityForResult(intent,TAKE_PHOTO);
                //调用会返回结果的开启方式,返回成功的话,则把它显示出来
            }
        });
    }
    //处理返回结果的函数,下面是隐示Intent的返回结果的处理方式,具体见以前我所发的intent讲解
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        switch (requestCode)
        {
            case TAKE_PHOTO:
                if(resultCode==RESULT_OK)
                {
                    try
                    {
                         Bitmap bitmap= BitmapFactory.decodeStream(getContent-
                                Resolver().openInputStream(imageUri));
                         picture.setImageBitmap(bitmap);
                         //将图片解析成Bitmap对象,并把它显现出来
                    }
                    catch (FileNotFoundException e)
                    {
                        e.printStackTrace();
                    }
                }
                break;
            default:
                break;
        }
    }
}

 第三步 刚刚我们提到了内容提供器,所以我们现在内容提供器在manifest.xml中进行注册,其中android:name的值是固定的,

android:authorities的值必须和FileProvider.getUriForFile的第二个参数是一致的,在这里面我们还利用了<meta-data来制定uri路径,并引用一个资源,当然这个资源还未创建,我们在第四步创建它。

<provider
            android:authorities="com.example.cameraalbumtest.fileprovider"
            android:name="android.support.v4.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

 第四步 在res目录下创建一个xml目录,目录是directory,之后在这个目录下,创建一个xml源文件,修改代码如下:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="my_images"
        path=""/>

</paths>

其中 <external-path用于指定uri共享的,名字可以随便填,path为空表示可以共享整个sd卡 

第五步 为了兼容老版本的安卓系统,我们还是打算添加一条权限,用于声明访问sd卡的权限。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

 

2015-06-11 13:50:26 liliangjuan 阅读数 472
  • Android底层技术:HAL驱动开发

    本课程提供开发者学习Android底层的HAL(硬件抽象层)的开发方法和技术。HAL所在的位置是介于Android系统服务与Linux内核之间,HAL Driver是以library形式出现,给HAL Stub调用,供Android System架构者调用。而HAL Stub则是google设计出来的,保护硬件厂商的硬件驱动。

    17829 人正在学习 去看看 高煥堂

本例在调用摄像头实现拍照中,可以调整拍照以及保存的照片的方向,调节焦距,并实现自动对焦


package com.example.camera1;


import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.xmlpull.v1.XmlPullParser;


import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.text.format.DateFormat;
import android.util.Log;
import android.util.Xml;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Toast;


public class CameraActivity extends Activity {


private SurfaceView surfaceView;
private Button saveButton;
private Button cancelButton;
private Camera camera;
private SeekBar seekBar;
private int setFixPictureWidth = 0;//设置最适合当前手机的图片宽度
private int setFixPictureHeight = 0;//设置最适合当前手机的图片高度
private int maxPictureSize = 5000000;//设置一个固定的最大尺寸
private SurfaceHolder surfaceHolder;
private String photoPath = "/sdcard/";// 照片保存路径
private Boolean isSupportAutoFous = false;// 是否支持自动聚焦,默认不支持
private String photoName;
private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
try {// 获得图片
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
String photoName = new DateFormat().format("yyyyMMdd_hhmmss",
Calendar.getInstance(Locale.CHINA)) + ".jpg";
File file = new File(photoPath + photoName1);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(file));
bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);// 将图片压缩到流中
bos.flush();// 输出
bos.close();// 关闭
} catch (Exception e) {
e.printStackTrace();
}
// camera.startPreview();
}
};


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
// 设置拍摄方向
// this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
surfaceView = (SurfaceView) findViewById(R.id.camera_priview);
saveButton = (Button) findViewById(R.id.camera_save);
cancelButton = (Button) findViewById(R.id.camera_cancel);
seekBar = (SeekBar) findViewById(R.id.seekbar_zoom);


seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub
}

@Override
public void onStartTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub
}

@Override
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
// TODO Auto-generated method stub
setZoom(seekBar.getProgress());
}
});


isSupportAutoFous = this.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA_AUTOFOCUS);
surfaceHolder = surfaceView.getHolder();
// 设置surface不需要自己的维护缓存区
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(surfaceCallback);
saveButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Camera.Parameters parameters = setCameraParms();
camera.setParameters(parameters);
camera.takePicture(null, null, pictureCallback);
}
});
cancelButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
camera.startPreview();
}
});

SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
// 关闭预览并释放资源
camera.stopPreview();
camera.release();
camera = null;
}


@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera = Camera.open();
Log.e("CameraActivity", "摄像头Open完成");
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
camera.release();
camera = null;
}
}


@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
Camera.Parameters parameters = setCameraParms();

List<Camera.Size> mSupportedsizeList = parameters.getSupportedPictureSizes();
if (mSupportedsizeList.size() > 1) {
Iterator<Camera.Size> itos = mSupportedsizeList.iterator();
while (itos.hasNext()) {
Camera.Size curSize = itos.next();
int carSupportSize = curSize.width * curSize.height;
int fixPictureSize = setFixPictureWidth * setFixPictureHeight;
if (carSupportSize > fixPictureSize
&& fixPictureSize < maxPictureSize) {
setFixPictureWidth = curSize.width;
setFixPictureHeight = curSize.height;
}
}
}
if (setFixPictureWidth != 0 && setFixPictureHeight != 0){
parameters.setPictureSize(setFixPictureWidth, setFixPictureHeight);
parameters.setJpegQuality(100);
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
}

camera.startPreview();
if (isSupportAutoFous) {
camera.autoFocus(new AutoFocusCallback() {
@Override
public void onAutoFocus(boolean focused, Camera camera) {
// TODO Auto-generated method stub

/*实现自动对焦拍照

if(focused){

Camera.Parameters parameters = setCameraParms();
camera.setParameters(parameters);
camera.takePicture(null, null, pictureCallback);

}*/
}
});
}
}


};

/**
* 方向变化监听器,监听传感器方向的改变
*/
public class MyOrientationDetector extends OrientationEventListener {
int Orientation;

public MyOrientationDetector(Context context) {
super(context);
}

@Override
public void onOrientationChanged(int orientation) {
Log.i("MyOrientationDetector ", "onOrientationChanged:"
+ orientation);
this.Orientation = orientation;
Log.d("MyOrientationDetector", "当前的传感器方向为" + orientation);
}

public int getOrientation() {
return Orientation;
}
}


/** 设置相机焦距 **/
private void setZoom(int mValue) {
seekBar.setMax(camera.getParameters().getMaxZoom());
Camera.Parameters parameters = camera.getParameters();
parameters.setZoom(mValue);
camera.setParameters(parameters);
}

private Camera.Parameters setCameraParms(){
MyOrientationDetector cameraOrientation = new MyOrientationDetector(
CameraActivity.this);
int orientation = cameraOrientation.getOrientation();

Camera.Parameters parameters = camera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG);
parameters.setPreviewSize(800, 480);
parameters.setRotation(90);
parameters.set("rotation", 90);
if ((orientation >= 45) && (orientation < 135)) {
parameters.setRotation(180);
parameters.set("rotation", 180);
}
if ((orientation >= 135) && (orientation < 225)) {
parameters.setRotation(270);
parameters.set("rotation", 270);
}
if ((orientation >= 225) && (orientation < 315)) {
parameters.setRotation(0);
parameters.set("rotation", 0);
}
return parameters;
}

@Override
protected void onDestroy() {
super.onDestroy();
// File file = new File(photoPath + photoName);
// if (file.exists()) {
// file.delete();
}
}
}



布局文件activity_camera.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"
    tools:context=".CameraActivity" >

    <RelativeLayout
        android:id="@+id/a"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <SurfaceView
            android:id="@+id/camera_priview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical|center_horizontal"
            android:layout_marginBottom="55dp" />

        <SeekBar
            android:id="@+id/seekbar_zoom"
            android:layout_width="300dp"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_gravity="center_vertical"
            android:layout_marginBottom="55dp"
            android:progressDrawable="@drawable/seekbar_style"
            android:thumb="@drawable/ic_launcher"
            android:thumbOffset="0dp" />
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/a" 
        android:background="#000">

        <Button
            android:id="@+id/camera_save"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:background="#000"
            android:textColor="#fff"
            android:text="拍照" />

        <Button
            android:id="@+id/camera_cancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:background="#000"
            android:textColor="#fff"
            android:text="取消" />
    </RelativeLayout>

</RelativeLayout>



添加权限

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-permission 
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />


2014-05-06 16:23:23 chenzheng8975 阅读数 65
  • Android底层技术:HAL驱动开发

    本课程提供开发者学习Android底层的HAL(硬件抽象层)的开发方法和技术。HAL所在的位置是介于Android系统服务与Linux内核之间,HAL Driver是以library形式出现,给HAL Stub调用,供Android System架构者调用。而HAL Stub则是google设计出来的,保护硬件厂商的硬件驱动。

    17829 人正在学习 去看看 高煥堂

添加权限:

 <!-- 摄像头权限 -->
    <uses-permission android:name="android.permission.CAMERA"/>
    <!-- SD卡读写权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

 

关键代码:

 

/**  
	 * @ClassName: addPictureListenerImpl  
	 * @Description: 添加图片
	 * @author chenzheng
	 * @date 2014-5-6 下午2:51:46  
	 */
	private class addPictureListenerImpl implements OnClickListener {

		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
			startActivityForResult(intent,1);
		}
		
	}
	
	protected void onActivityResult(int requestCode, int resultCode,
			Intent data) {
		if (requestCode == 1) {
			if (resultCode == RESULT_OK) {
				Bundle bm = data.getExtras();
				Bitmap bitmap = (Bitmap) bm.get("data");
				pic1.setImageBitmap(bitmap);
			}
		}
	}

 

 

Demo如下:

博文 来自: weixin_43344890
没有更多推荐了,返回首页