2017-05-05 17:42:28 a1027317350 阅读数 2066
  • Android底层技术:HAL驱动开发

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

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

  因为Android6.0之后,Android系统的安全级别升级,我们的项目都需要去适配Android6.0和Anroid7.0,Android6.0加入了运行时权限申请,Android主要对SD卡的读写做了更加严格的要求,所以本来简单的调用相机和从相册选择一张图片的逻辑便的稍微复杂了那么一点。

    言归正传,我们先来谈谈如何调用相机吧。

     调用相机

        //调用getExternalCacheDir()可以得到应用关联缓存目录,
        // Android6.0之后读写SD卡被列为了危险权限,而这个目录不需要申请权限,
        File temp = new File(getContext().getExternalCacheDir(),System.currentTimeMillis() + ".jpg");
        try {
            if (temp.exists()) {
                temp.delete();
            }
            temp.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Uri imageFileUri = null;
        if (Build.VERSION.SDK_INT >= 24) {
             //如果是7.0 以上的版本就必须使用这个方法,
            // 第一个参数是context,第二个参数可以是任意唯一的字符窜,
            // 第三参数是我们刚刚建立的file对象。
            //因为7.0以后直接使用本地真实路径的Uri本认为是不安全的,会抛出FileUriExposedException异常的
            //而FileProvider这是一种特殊的内容提供器,它使用了和内容提供器类似的机制来对数据进行保护,
            // 可以选择性的将封装过的Uri共享给外部,从而提高了应用的安全性。
            imageFileUri = FileProvider.getUriForFile(getContext(),"com.example.cameratest.fileprovider",temp);
        } else {
             imageFileUri = Uri.fromFile(temp);//获取文件的Uri
        }
        Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//跳转到相机Activity
        it.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageFileUri);//告诉相机拍摄完毕输出图片到指定的Uri
       startActivityForResult(it, 102);
 然后在onActivityResult()方法中去把这张照片转换为bitmap格式的就OK了

       Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
 当然我们刚刚用到了FileProvider,我们需要为其注册一下

           <provider
            android:authorities="com.example.cameratest.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>

其中android:name的值是固定的,android:authorities属性值必须与FileProvider.getUriForFile()中第二个参数写的一致,另外还需要使用<meta-data>标签来指定Uri的共享路径,并引用一个@xml/file_path资源,当然这个需要我们创建

    

<?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共享的,name可以随便填,path的值表示共享的具体路径,空值代表将整个SD卡共享,当然也可以只共享test.jpg这张图片的路径。

另外一点需要注意,在Android4.4之前,访问SD卡的应用关联目录也是需要声明权限的,4.4系统之后不需要再声明,为了兼容,我们最好声明一下SD卡的访问权限。

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

相册中选择图片

我们需要动态申请WRITE_EXTERNAL_STORGAGE这个权限,打开相册去选择图片,打开相册很简单,不再写代码了,我们主要讲一下如何处理返回的这张图片。因为Android4.4之后,选取相册中的图片不再返回图片真实额Uri了,而是一个封装过的Uri,所以我们需要对这个Uri进行解析。下面是4.4以上系统处理图片的代码。
/**
     * 4.4以上系统使用这个方法处理图片
     * @param data
     */
    public handleImageOnKitKat(Intent data) {
        String imagePath = null;
        Uri uri = data.getData();
        if (DocumentsContract.isDocumentUri(this,uri)){
            //如果是document类型的uri,则通过document id来处理
            String docId = DocumentsContract.getDocumentId(uri);
            if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                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://download/public_downloads"),Long.valueOf(docId));
                imagePath = getImagePath(contentUri,null);
            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            //如果是content类型的Uri,则使用普通的方式处理
            imagePath = getImagePath(uri,null);
        } else if ("file".equalsIgnoreCase(uri.getScheme())){
            //如果是file类型的Uri,则直接获取图片路径即可
            imagePath = uri.getPath();
        }
        //根据图片路径去显示图片
        ....
    }

    private String getImagePath(Uri uri,String selection){
        String path = null;
        Cursor cursor = getContext().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;
    }
而4.4之前就比较简单的,它的Uri并没有被封装过,不需要任何解析。

    private void handleImageBeforeKitKat(Intent data) {
        Uri uri = data.getData();
        String imagePath = getImagePath(uri,null);
        //根据图片路径去显示图片
        ....
    }
下面是压缩图片代码,我觉得还是不错的,有需要的大家可以借鉴一下

 public static Bitmap getBitMapByUri(String path, String outPath) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        opts.inPreferredConfig = Bitmap.Config.RGB_565;
        Bitmap bitmap = BitmapFactory.decodeFile(path, opts);

        int w = opts.outWidth;
        int h = opts.outHeight;
        // 现在主流手机比较多是800*480分辨率
        float hh = 800f;// 这里设置高度800f
        float ww = 480f;// 这里设置宽度480f
        // 缩放比由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
        // 计算缩放比
        int be = 1;
        if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
            be = Math.round((opts.outWidth / hh));
        } else if (w < h && h > hh) {// 如果高度高的话根据高度固定大小缩放
            be = Math.round((opts.outHeight / hh));
        }

        if (be <= 0) {
            be = 1;
        }
        opts.inSampleSize = be;
        opts.inJustDecodeBounds = false;

        bitmap = BitmapFactory.decodeFile(path, opts);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//
        // 质量压缩方法,这100表示不压缩,把压缩后的数据存放到baos中
        int option = 100;

        if (baos.toByteArray().length / 1024 > 100) { // 按照比例缩放完毕后,判断图片质量任然大于100KB,再次进行缩放?
            while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
                baos.reset();// 重置baos即清空baos
                bitmap.compress(Bitmap.CompressFormat.JPEG, option, baos);// 这里压缩options%,把压缩后的数据存放到baos中
                option -= 10;// 每次都减去10
            }
            /*ByteArrayInputStream isBm = new ByteArrayInputStream(
					baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
			// ;// 把ByteArrayInputStream数据生成图片
			bitmap = BitmapFactory.decodeStream(isBm, null, null);*/
            FileOutputStream fos = null;
            try {
                if (!FileUtils.fileIsExists("")) {
                    FileUtils.createSDDir("photo");
                }
                File file = new File(outPath);
                if (file.exists()) {
                    file.delete();
                }
                fos = new FileOutputStream(file);
                fos.write(baos.toByteArray());
                fos.flush();
                fos.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bitmap;
    }


这些知识都是平常项目中很常用的,大家可以看看,如果有不懂的可以给我留言哈,今天就总结到这里吧,

2012-07-16 20:10:58 ziyanguang1989 阅读数 3231
  • Android底层技术:HAL驱动开发

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

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

很多同学在做客户端的时候,都需要做上传图片,那么上传图片如何上传呢?自己写一个SurfaceView做为展示区,然后用camera类来实现?太out了!直接调用相机拍照获取或者调用相册来取照片才是王道

首先:

1.首先在AndroidManifest.xml中设置权限:


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


2.调用相机和相册:


Intent takephoto = newIntent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takephoto,CAPTURE_CODE);


Intent album = newIntent(Intent.ACTION_GET_CONTENT);
album.setType("image/*");
startActivityForResult(album, IMAGE_CODE);


因为需要调用到返回值,所以必须使用startActivityForResult(Intentintent,int result);


3.写onActivityResult方法接返回值


@Override
protected void onActivityResult(int requestCode, int resultCode,Intent data) {
try {
ContentResolver resolver = getContentResolver();
if (resultCode != RESULT_OK) {
return;
} else if (requestCode == IMAGE_CODE) {
Uri originalUri = data.getData();
if (originalUri != null) {
bm = MediaStore.Images.Media.getBitmap(resolver,originalUri);
iv.setImageBitmap(bm);
}
} else if (requestCode == CAPTURE_CODE&& resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
if (bundle != null) {
bm = (Bitmap) bundle.get("data");
iv.setImageBitmap(bm);
}
}
} catch (Exception e) {
Toast.makeText(this, "选择图片错误,图片只能为jpg格式",Toast.LENGTH_SHORT).show();
}
}


至此,bitmap已经返回并且已经赋值给了界面上的ImageView。


友情提示:如何将bitmap转成byte[]?晓飞告诉你:


private byte[] Bitmap2Bytes(Bitmap bm){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}


2016-10-26 14:37:47 ak4100 阅读数 8966
  • Android底层技术:HAL驱动开发

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

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


安卓代码:MainActivity.java

package com.xx.xxx; //对应unity的包名

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

import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;

import android.app.Activity;
import android.content.ContentResolver;
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.MediaStore;
import android.util.Log;

public class MainActivity extends UnityPlayerActivity {
//public class MainActivity extends Activity {

	private static final String TAG = MainActivity.class.getSimpleName();
	private static final int PHOTO_REQUEST_CODE = 1;//相册
	public static final int PHOTOHRAPH = 2;// 拍照
	private static final boolean DEBUG = false;
//	private String unitygameobjectName = "Main Camera";
	private String unitygameobjectName = "BGPlane"; //Unity 中对应挂脚本对象的名称
	public static final int NONE = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        OpenGallery();
    }
    
    //调用相机
    public void takephoto(){
    	
    	 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
         intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "temp.jpg")));
         startActivityForResult(intent, PHOTOHRAPH);
    	
    }
    
    //调用相册
    public void OpenGallery()
    {
	   Intent intent = new Intent(Intent.ACTION_PICK,null);
	   intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,"image/*");
	   startActivityForResult(intent, PHOTO_REQUEST_CODE);
    }
   
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	// TODO Auto-generated method stub
	   super.onActivityResult(requestCode, resultCode, data);
	   if (resultCode == NONE){
		   return;
	   }
	   if(PHOTO_REQUEST_CODE == requestCode){
		   if(data == null){
			   return;
		   }
		   Uri uri = data.getData();
		   String imagePath = getImagePath(uri);
		   if(DEBUG){
			   Log.d(TAG, imagePath);
		   }
		   //调用unity中方法 GetImagePath(imagePath)
		   UnityPlayer.UnitySendMessage(unitygameobjectName, "GetImagePath", imagePath);
	   }
	   
	   if (requestCode == PHOTOHRAPH) {
           String path = Environment.getExternalStorageDirectory() + "/temp.jpg";
           if(DEBUG){
        	   Log.e("path:", path);
           }
           //调用unity中方法 GetTakeImagePath(path)
           UnityPlayer.UnitySendMessage(unitygameobjectName, "GetTakeImagePath", path);
           try {
        	   Bitmap bitmap = BitmapFactory.decodeFile(path);  
        	   SaveBitmap(bitmap);
			} catch (IOException e) {
				e.printStackTrace();
			}
       }  
    }
    
    private String getImagePath(Uri uri)
    {
    	if(null == uri) return null;
    	String path = null;
        final String scheme = uri.getScheme();
        if (null == scheme) {
            path = uri.getPath();
        } else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            path = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            String[] proj = { MediaStore.Images.Media.DATA };
            Cursor cursor = getContentResolver().query(uri, proj, null, null,
                    null);
            int nPhotoColumn = cursor
                    .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            if (null != cursor) {
                cursor.moveToFirst();
                path = cursor.getString(nPhotoColumn);
            }
            cursor.close();
        }
		return path;
    }
    
    public void SaveBitmap(Bitmap bitmap) throws IOException {
    	
		FileOutputStream fOut = null;
		String path = "/mnt/sdcard/DCIM/"; 
		try {
			  //查看这个路径是否存在,
			  //如果并没有这个路径,
			  //创建这个路径
			  File destDir = new File(path);
			  if (!destDir.exists())
			  {
				  destDir.mkdirs();
			  }
            String FILE_NAME = System.currentTimeMillis() + ".jpg"; 
			fOut = new FileOutputStream(path + "/" + FILE_NAME) ;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		//将Bitmap对象写入本地路径中
		bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
		try {
			fOut.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			fOut.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xx.xxx"
    android:versionCode="1"
    android:versionName="1.0" >
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="23" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        >
        <activity
            android:name="com.xx.xxx.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>
    
</manifest>


Unity 代码:AndroidPhoto.cs

using UnityEngine;
using System.Collections;

public class AndroidPhoto : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
        //打开相册	
	public void OpenPhoto()
	{
		AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
		AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
		jo.Call("OpenGallery");       
	}
        
        //打开相机
	public void OpenCamera()
	{
		AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
		AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
		jo.Call("takephoto");       
	}

	public void GetImagePath(string imagePath)
	{ 
		if (imagePath == null)
			return;
		StartCoroutine("LoadImage",imagePath);
	}

	public void GetTakeImagePath(string imagePath)
	{
		if (imagePath == null)
			return;
		StartCoroutine("LoadImage",imagePath);
	}
		
	private IEnumerator LoadImage(string imagePath)
	{
		WWW www = new WWW ("file://"+imagePath);
		yield return www;
		if (www.error == null) {
                       //成功读取图片,写自己的逻辑
			GetComponent<ChangePhoto>().LoadAndroidImageOK(www.texture);
		}else{
			Debug.LogError("LoadImage>>>www.error:"+www.error);
		}
	}
}

注意:1.android包名要和unity保持一致  

            2.unitygameobjectName要对应   

            3.须将unity下的classes.jar拷贝至安卓工程libs下方可正确编译再导出为jar包,unity5.4.1 下classes.jar 地址:C:\Program Files\Unity_5_4_1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Development\Classes
         


2019-06-18 18:15:46 weixin_43484014 阅读数 258
  • Android底层技术:HAL驱动开发

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

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

Android调用相机和相册详解

主要是想实现头像的更改

xml内容

我用的是XUI的自定义控件 gradient_background是自定义的渐变背景色

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rootView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <LinearLayout
        android:id="@+id/nodata"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/gradient_background"
        android:gravity="center"
        android:orientation="vertical"
        >
        <com.xuexiang.xui.widget.imageview.RadiusImageView
            android:id="@+id/headImage"
            android:clickable="true"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:src="@drawable/default_head_img"
            app:riv_border_color="@color/xui_config_color_gray_6"
            app:riv_border_width="1px"
            app:riv_is_circle="true"
            app:riv_selected_border_color="@color/xui_config_color_gray_4"
            app:riv_selected_border_width="1px"
            android:layout_marginBottom="80dp"
            app:riv_selected_mask_color="@color/xui_config_color_gray_8"/>
    </LinearLayout>
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never"
        tools:listitem="@android:layout/simple_list_item_2" />
</LinearLayout>

gradient_background.xml内容如下,渐变色背景

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

    <!-- 变化率 -->
    <gradient
        android:endColor="#c1efbb"
        android:centerColor="#c2eaf3"
        android:startColor="#56d1ea" />
</shape>

实现的页面效果如下
Alt

activity部分

package cn.lision.mas.activity.mine;

import android.Manifest;
import android.annotation.TargetApi;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.view.View;

import com.xuexiang.xui.widget.actionbar.TitleBar;
import com.xuexiang.xui.widget.dialog.bottomsheet.BottomSheet;
import com.xuexiang.xui.widget.imageview.RadiusImageView;
import com.xuexiang.xutil.tip.ToastUtils;

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

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import cn.lision.mas.R;
import cn.lision.mas.base.BaseActivity;

/**
 * 头像更换
 */
public class HeadChangeActivity extends BaseActivity {

    private Context context;
    private RadiusImageView headImage;

    private Uri imageUri;

    public static final int TAKE_PHOTO = 1;
    public static final int CHOOSE_PHOTO = 2;
    private String orientation = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_head_change);
        context = this;
        TitleBar titleBar = initTitle("更换头像");
        initViews();

    }

    @Override
    public void initViews() {
        headImage = (RadiusImageView) findViewById(R.id.headImage);
        headImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showSimpleBottomSheetList();
            }
        });


    }

    private void showSimpleBottomSheetList() {
        new BottomSheet.BottomListSheetBuilder(context)
                .addItem("从相册选择图片")
                .addItem("拍照")
                .addItem("取消")
                .setIsCenter(true)
                .setOnSheetItemClickListener(new BottomSheet.BottomListSheetBuilder.OnSheetItemClickListener() {
                    @Override
                    public void onClick(BottomSheet dialog, View itemView, int position, String tag) {
                        dialog.dismiss();
                        if (position == 0) {
                            if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                                ActivityCompat.requestPermissions(HeadChangeActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);
                            } else {
                                goPhotoAlbum();
                            }
                        } else if (position == 1) {
                            File file = new File(getExternalCacheDir(), "output_image.jpg");
                            try {
                                if (file.exists()) {
                                    file.delete();
                                }
                                file.createNewFile();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }

                            if (Build.VERSION.SDK_INT >= 24) {
                                imageUri = FileProvider.getUriForFile(HeadChangeActivity.this, "com.example.cameraalbumtest.fileprovider", file);
                            } else {
                                imageUri = Uri.fromFile(file);
                            }

                            if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                                ActivityCompat.requestPermissions(HeadChangeActivity.this, new String[]{Manifest.permission.CAMERA}, 1);
                            } else {
                                callCamera();
                            }
                        } else {
                            dialog.dismiss();
                        }
                    }
                })
                .build()
                .show();
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case TAKE_PHOTO:
                if (resultCode == RESULT_OK) {
                    try {
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
                        headImage.setImageBitmap(bitmap);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case CHOOSE_PHOTO:
                if (resultCode == RESULT_OK) {
                    //判断手机系统版本号
                    if (Build.VERSION.SDK_INT >= 19) {
                        //4.4及以上系统使用
                        handleImageOnKitKat(data);
                    } else {
                        handleImageBeforeKitKat(data);
                    }
                }
                break;
            default:
                break;
        }
    }

    //激活相册操作
    private void goPhotoAlbum() {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType("image/*");
        startActivityForResult(intent, CHOOSE_PHOTO);
    }

    //打开相机
    private void callCamera() {
        //启动相机权限
        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        startActivityForResult(intent, TAKE_PHOTO);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            //打开相册
            case CHOOSE_PHOTO:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    goPhotoAlbum();
                } else {
                    ToastUtils.toast("您没有打开相册的权限");
                }
                break;
            //相机的权限
            case TAKE_PHOTO:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    callCamera();
                } else {
                    ToastUtils.toast("您没有打开相机的权限");
                }
                break;
            default:
                break;
        }
    }

    @TargetApi(19)
    private void handleImageOnKitKat(Intent data) {
        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];
                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())) {
            //如果是content类型的Uri,则使用普通方式处理
            imagePath = getImagePath(uri, null);
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            imagePath = uri.getPath();
        }
        dispalyImage(imagePath);
    }

    private void handleImageBeforeKitKat(Intent data) {
        Uri uri = data.getData();
        String imagePath = getImagePath(uri, null);
        dispalyImage(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));
            }
            orientation = cursor.getString(cursor.getColumnIndex("orientation"));// 获取旋转的角度
            cursor.close();
        }
        return path;
    }

    private void dispalyImage(String imagePath) {
        if (imagePath != null) {
            //根据path读取资源路径
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            int angle = 0;
            if (orientation != null && !"".equals(orientation)) {
                angle = Integer.parseInt(orientation);
            }
            if (angle != 0) {
                // 下面的方法主要作用是把图片转一个角度,也可以放大缩小等
                Matrix m = new Matrix();
                int width = bitmap.getWidth();
                int height = bitmap.getHeight();
                m.setRotate(angle); // 旋转angle度
                bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, m, true);// 从新生成图片
            }
            headImage.setImageBitmap(bitmap);
        } else {
            ToastUtils.toast("获取照片失败");
        }
    }
}

最终实现的结果

在这里插入图片描述)
在这里插入图片描述
在这里插入图片描述

啦啦啦 更换成功啦

2017-06-08 15:07:58 RcyYangYang 阅读数 301
  • Android底层技术:HAL驱动开发

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

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

Android 调用系统相机和相册

MainActivity

package com.example.photoxc_demo;


import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity implements View.OnClickListener {
    private Button btnCamera;
    private Button btnGallery;
    private ImageView imageView;
    private Intent intent;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnCamera = (Button) findViewById(R.id.mBtn1);
        btnCamera.setOnClickListener(this);
        btnGallery = (Button) findViewById(R.id.mBtn2);
        btnGallery.setOnClickListener(this);
        imageView = (ImageView) findViewById(R.id.mImg);
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Bitmap bitmap=CameraGallaryUtil.getBitmapFromCG(this,requestCode,resultCode,data);
        imageView.setImageBitmap(bitmap);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.mBtn1:
                // 利用系统自带的相机应用:拍照
                intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                // 此处这句intent的值设置关系到后面的onActivityResult中会进入那个分支,即关系到data是否为null
                // 如果此处指定,则后来的data为null
                // 只有指定路径才能获取原图
                intent.putExtra(MediaStore.EXTRA_OUTPUT, CameraGallaryUtil.fileUri);
                startActivityForResult(intent, CameraGallaryUtil.PHOTO_REQUEST_TAKEPHOTO);
                break;
            case R.id.mBtn2:
                intent = new Intent(Intent.ACTION_PICK, null);
                intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
                startActivityForResult(intent, CameraGallaryUtil.PHOTO_REQUEST_GALLERY);
                break;
        }
    }
}

CameraGallaryUtil

package com.example.photoxc_demo;
import java.io.File;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
public class CameraGallaryUtil {
    private static final int RESULT_OK = -1;
    public static final int PHOTO_REQUEST_TAKEPHOTO = 1;// 拍照
    public static final int PHOTO_REQUEST_GALLERY = 2;// 从相册中选择
    public static final int PHOTO_REQUEST_CUT = 3;// 裁剪结果
    public static final Uri fileUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory()
            .getPath() + File.separator + "temp.jpg"));//临时储存的Uri
    public static Bitmap getBitmapFromCG(Activity activity, int requestCode, int resultCode, Intent data) {
        Bitmap bitmap = null;
        switch (requestCode) {
            // 如果是拍照
            case PHOTO_REQUEST_TAKEPHOTO:
                if (resultCode == RESULT_OK) {
                    // 没有指定特定存储路径的时候,data不为null
                    if (data != null) {
                        if (data.getData() != null) {
                            startPhotoZoom(activity, data.getData());
                        }
                    } else {
                        startPhotoZoom(activity, fileUri);
                    }
                }
                break;
            // 如果是从相册选取
            case PHOTO_REQUEST_GALLERY:
                if (data != null) {
                    if (data.getData() != null) {
                        startPhotoZoom(activity, data.getData());
                    }
                }
                break;
            //如果是裁剪完成
            case PHOTO_REQUEST_CUT:
                if (data != null) {
                    Bundle bundle = data.getExtras();
                    if (bundle != null) {
                        bitmap = bundle.getParcelable("data");
                    }
                }
                break;
        }
        return bitmap;
    }

    private static void startPhotoZoom(Activity activity, Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        // crop为true是设置在开启的intent中设置显示的view可以剪裁
        intent.putExtra("crop", "true");
        //aspectX aspectY 是宽高的比例
        intent.putExtra("aspectX", 300);
        intent.putExtra("aspectY", 400);
        //outputX,outputY 是剪裁图片的宽高
        intent.putExtra("outputX", 300);
        intent.putExtra("outputY", 400);
        intent.putExtra("return-data", true);
        activity.startActivityForResult(intent, PHOTO_REQUEST_CUT);
    }
}

//以下是xml布局:

activity

<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="com.example.photoxc_demo.MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" 
        android:orientation="vertical"
        >
        <Button
            android:id="@+id/mBtn1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="相机" />

        <Button
            android:id="@+id/mBtn2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="相册" />

        <ImageView
            android:id="@+id/mImg"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>
</RelativeLayout>

//需要添加的权限:

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





没有更多推荐了,返回首页