因为搜了好多资料,内容差不多,但是看的好蛋疼,就写了个。照相机实现!!-阿里云开发者社区

开发者社区> 王亟亟> 正文

因为搜了好多资料,内容差不多,但是看的好蛋疼,就写了个。照相机实现!!

简介:
+关注继续查看

如若转载请注明:王亟亟的大牛之路

在贴代码和讲实践之前先上图,让各位看官知道这是什么玩意
初始化的视图,就一个Activity
这里写图片描述
拍照时的状态,因为不是美图秀秀啊之类的摄像软件,所以这个清晰度已经够了
这里写图片描述
选择相册内图片的截图
这里写图片描述

先来说下Camera类
Android手机关于Camera的使用,一是拍照,二是摄像。
我们可以使用两类方法:一是借助Intent和MediaStroe调用系统Camera App程序来实现拍照和摄像功能,二是根据Camera API自写Camera程序。(例子是第一种,因为对拍摄内容没有更多的要求)

授权
在AndroidMainfest.xml中声明使用照相机.
Camera权限, 你必须在AndroidMainfest.xml中声明使用照相机的权限,例如

注:如果你是调用系统Camera程序的话,就不必声明
Camera特性,你必须在AndroidMainfest.xml中声明照相机特性,例如:

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

如果你的程序可能需要使用照相机,但并不是一定的,那么可以设置android:required属性,比如:

<uses-feature android:name="android.hardware.camera"android:required="false" />

存储权限,如果你的程序想在扩展存储设备上(如sd卡)存储你的照片或者拍摄的视频,那么必须声明如下权限:

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

音频录制权限, 为了录制音频或者视频,你必须在AndroidMainfest.xml文件中设置如下权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" />

使用系统Camera程序
这是一种可以让你的程序以最少的编码,然后可以快速使用照相机的方法,它通过一个Intent来调用系统的Camera程序。一个Camera的intent可以发起一个请求,来让系统的Camera应用程序去拍摄照片或者录制视频,而且可以返回拍摄或者录制的结果给你自己的应用程序,那么接下来,我们将讨论如何使用这种方法。

i. 构造一个Camera Intent – 创建一个拍摄照片或者视频的Intent, 我们可以使用如下两种方法:
MediaStore.ACTION_IMAGE_CAPTURE – 一个intent action,用来向系统Camera程序请求拍摄图片。
MediaStore.ACTION_VIDEO_CAPTURE – 一个intent action, 用来向系统Camera程序请求录制视频。

ii. 开启Camera intent – 通过调用startActivityForResult()来执行Camera intent, 在你调用这个方法之后,系统Camera程序就是出现在用户界面,然后用户就可以拍摄照片或者视频了。

iii. 接收Intent 结果 – 在你的应用程序里面建立一个onActivityResult()方法来接收来自系统Camera程序的执行结果。当用户拍摄了照片或者视频(也许取消了拍摄操作),系统就会调用这个方法。

图片拍摄Intent
使用系统Camera来拍摄图片,是一种以最快的速度,最少的代码,让你的程序能够拍照的方法。一个图片拍摄的intent可以包含如下扩展信息:
i. MediaStore.EXTRA_OUTPUT – 指定一个Uri对象,系统Camera程序会把拍摄的图片存储到指定位置。这个设置一般是强烈推荐的。如果你不指定这个Uri路径,那么系统Camera程序会把图片以一个默认的名字,存储在一个默认的位置。我们可以通过返回的intent,然后用Intent.getData()方法来获取这个值。

ii. 下面这个例子可以告诉大家怎么构造一个拍摄图片的intent,并且执行它。

private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
    private Uri fileUri;
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); 
    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
    startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
    }

当startActivityForResult()方法执行之后,用户就会看到系统的Camera界面。当用户完成拍摄照片(或者取消拍摄)之后,用户界面就会返回你自己的应用程序。那么你必须拦截onActivityResult方法,以便接收执行结果和继续你自己代码的逻辑。

**c. 视频录制intent**
使用系统Camera来录制视频,是一种以最快的速度,最少的代码,让你的程序能够录制视频的方法。一个视频录制的intent可以包含如下扩展信息:

MediaStore.EXTRA_OUTPUT -- 指定一个Uri对象,系统Camera程序会把录制的视频存储到指定位置。这个设置一般是强烈推荐的。如果你不指定这个Uri路径,那么系统Camera程序会把视频以一个默认的名字,存储在一个默认的位置。我们可以通过返回的intent,然后用Intent.getData()方法来获取这个值。

MediaStore.EXTRA_VIDEO_QUALITY -- 视频质量,0(低质量,比较小的文件来存储视频), 1(高质量,比较大的文件来存储视频)

MediaStore.EXTRA_DURATION_LIMIT  -- 设置一个值来限制视频时间长度,秒为单位。

MediaStore.EXTRA_SIZE_LIMIT -- 设置一个值来限制视频大小,byte为单位。

**理论上的东西就讲这么些,源码和外面的翻译网上有,现在上代码!**
主Activity,就一个Activity

public class MainActivity extends ActionBarActivity implements View.OnClickListener {
//图片自定义控件
ImageView imageview;
//按钮控件
Button makephoto, choicephoto;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//检查策略
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads().detectDiskWrites().detectNetwork()
.penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects().detectLeakedClosableObjects()
.penaltyLog().penaltyDeath().build());

    //获取id,否则空指针
    findViewById();
    initListener();
}
  @Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}
   @Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
    private void findViewById() {
    imageview = (ImageView) findViewById(R.id.imageview);
    choicephoto = (Button) findViewById(R.id.choicephoto);
    makephoto = (Button) findViewById(R.id.makephoto);
}

private void initListener() {
    choicephoto.setOnClickListener(this);
    makephoto.setOnClickListener(this);
}
   //用于OnClickListener
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.makephoto:
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            long time = Calendar.getInstance().getTimeInMillis();
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment
                    .getExternalStorageDirectory() + "/DCIM/", time
                    + ".jpg")));
            startActivityForResult(intent, 1);
            break;
        case R.id.choicephoto:
            Intent intent2 = new Intent(Intent.ACTION_PICK, null);
            intent2.setDataAndType(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,// 获取所有图片信息
                    "image/*");
            startActivityForResult(intent2, 2);
            break;
        default:
            break;
    }
} 

    //拍照必须回调的方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == 0)
        return;
    // 拍照
    if (requestCode == 1) {
        // 设置文件保存路径
        File picture = new File(Environment.getExternalStorageDirectory()
                + "/tempImage.jpg");
        startPhotoZoom(Uri.fromFile(picture));
    }
    if (data == null)
        return; 

    // 读取相册缩放图片
    if (requestCode == 2 && resultCode == RESULT_OK
            && null != data) {
        Uri selectedImage = data.getData();
        String[] filePathColumn = {MediaStore.Images.Media.DATA};

        Cursor cursor = getContentResolver().query(selectedImage,
                filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();
        imageview.setImageBitmap(BitmapFactory.decodeFile(picturePath));
    }

    // 处理结果
    if (requestCode == 3) {
        Bundle extras = data.getExtras();
        if (extras != null) {
            Bitmap photo = extras.getParcelable("data");
            //File fImage = new File("D:\\sdcard.img");
            try {

                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                //FileOutputStream stream = new FileOutputStream(fImage);
                photo.compress(Bitmap.CompressFormat.JPEG, 75, stream);// (0-100)压缩文件

                stream.close();
            } catch (IOException e) {

                e.printStackTrace();
            }
            //ByteArrayOutputStream stream = new ByteArrayOutputStream();
            imageview.setImageBitmap(photo); // 把图片显示在ImageView控件上
        }
    }
    super.onActivityResult(requestCode, resultCode, data);
}

//剪裁图片
public void startPhotoZoom(Uri uri) {
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.setDataAndType(uri, "image/*");
    intent.putExtra("crop", "true");
    // aspectX aspectY 是宽高的比例
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    // outputX outputY 是裁剪图片宽高
    intent.putExtra("outputX", 300);
    intent.putExtra("outputY", 400);
    intent.putExtra("return-data", true);
    startActivityForResult(intent, 3);
}

}

<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"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:id="@+id/toolLayout">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="拍照"
            android:id="@+id/makephoto"
            android:layout_weight="1"
            android:background="@color/green"
            android:textColor="@color/white" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="选择相册"
            android:id="@+id/choicephoto"
            android:layout_weight="1"
            android:background="@color/white"
            android:textColor="@color/light_blue" />
    </LinearLayout>

    <RelativeLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_above="@+id/toolLayout"
        android:id="@+id/contentLayout">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/imageview"
            android:layout_gravity="clip_horizontal"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:background="@color/gray" />

    </RelativeLayout>
</RelativeLayout>

colors:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="gray">#5e5e5e</color>
    <color name="green">#ff00bf00</color>
    <!-- 白色 -->
    <color name="white">#FFFFFF</color>
    <!-- 浅蓝 -->
    <color name="light_blue">#005293</color>
</resources>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="example.wjj.camera">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

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

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

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>

具体功能还是看源码吧!
下载地址:http://yunpan.cn/cQXjwrrHXRIjf 访问密码 05e3
有问题欢迎QQ452270579联系!

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Solr5.3.1通过copyField设置多个field(字段)同时检索
  如果业务需要我们对多个field同时进行检索,有没有什么好的办法呢?非常幸运的是Solr为我们提供了copyField对多个field进行索引和检索。然而配置也非常简单。   修改schame.xml,添加   修改后的schema.xml如下:   保存后并重启tomcat并重建索即可。
795 0
.NET 构造Class返回多个json值
  上次总结使用DataTable返回多个值,后来看到一个小哥的返回方式和我的有所不同,便留意了一下。原来他构造一个Class,而我构造的是一个Table。   首先说说两者的区别:拿student举例,student1有学号,姓名,成绩,student2,student3...都有该属性。
769 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4615 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
9513 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
10784 0
.NET 构造DataTable返回多个json值
有时候我们使用Ajax链接一般处理程序需要返回多个值,然而这些数据并非在一个查询表内,此时便想到构造一个虚拟的DataTable,这样就可以返回多个值了(当然有很多办法,这是其中一种 )。
871 0
+关注
王亟亟
隐藏人物
54
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载