1.获取联系人列表,代码如下:
private String[] getContacts() {
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String[] projects = new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor cursor = getContentResolver().query(uri,projects,null,null,null);
String[] contacts = null;
int index=0;
try{
Log.i("Contact-C","count : "+cursor.getCount());
contacts = new String[cursor.getCount()];
cursor.moveToFirst();
while (!cursor.isAfterLast()){
String name = cursor.getString(0);
String number = cursor.getString(1);
Log.i("Contact-C",name+" : "+number+" --------------- index = "+index);
contacts[index] = name+" : "+number;
index++;
cursor.moveToNext();
}
}finally {
index = 0;
cursor.close();
}
return contacts;
}
Demo下载链接:github demo,在NormalDemo/app/build/outputs/apk/debug下有Demo apk可直接安装运行查看效果
2. 获取本地图片路径:
public void getLocalImagePath(){
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, REQ_SELECT_IMAGE);
}
上述代码是选择图片,在onActivityResult获取路径:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQ_SELECT_IMAGE){
Uri imageUri = data.getData();
String imagePath = getRealPathFromURI(data.getData());
}
}
private String getRealPathFromURI(Uri contentURI) {
String result;
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) { // Source is Dropbox or other similar local file path
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
3. Camera拍照并重定向照片存储位置以及显示
相机拍摄的照片较大,需要在设备的文件系统中存储。Context提供的基本目录和目录处理系统如下:
(1)File getFilesDir()
获取/data/data/<包名>/files目录。
(2)FileInputStream openFileInput(String name)
打开现有文件进行读取。
(3)FileOutputStream openFileOutput(String name, int mode)
打开文件进行写入,如果不存在就创建它。
(4)File getDir(String name, int mode)
获取/data/data/<包名>/目录的子目录(如果不存在就先创建它)。
(5)String[] fileList()
获取主文件目录下的文件列表。可与其他方法配合使用,如openFileInput(String)。
(6)File getCacheDir()
获取/data/data/<包名>/cache目录。应注意及时清理该目录,并节约使用。
我们打算用getFilesDir()来存储拍摄的照片,这时候有一个问题,系统Camera拍摄的照片都会存储在系统指定的目录下,我们可以使用Gallery浏览,那如何将拍摄的照片重定向存储到应有的所在的目录呢。
如果想共享文件给其他应用,或是接收其他应用的文件(如相机应用拍摄的照片),可以通 过ContentProvider把要共享的文件暴露出来。ContentProvider允许你暴露内容URI给其他应 用。在Android中,如果只是从其他应用接收一个文件,我们可以使用FileProvider,唯一需要做的就是做一些简单的配置,接下来介绍。
1. 配置AndroidManifest.xml:
<provider
android:authorities="org.doit.canvas.demo.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">
</meta-data>
</provider>
由于FileProvider是ContentProvider的子类,我们需要在AndroidManifest中进行声明。上述配置中,authorities是授权的权限,name则是FileProvider完整的包路径,exported表示除了授权的人和自己以外,其他人禁止使用FileProvider,grantUriPermissions用来给其他应用授权,允许其他人向你指定的Uri写入数据。meta-data告诉FileProvider该暴露那些文件。
file.xml文件如下:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="take_photo"
path="."></files-path>
</paths>
这是个描述性XML文件,其表达的意思是,把私有存储空间的根路径映射为take_photo。 这个名字仅供FileProvider内部使用,你不应去用它。
以上就是Manifest中的配置,以下是代码部分:
private void capturePhoto(){
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
boolean canTake = captureIntent.resolveActivity(getPackageManager()) != null;
Log.i("TakePhoto","canTake : "+canTake);
if (canTake){
Uri fileUri = FileProvider.getUriForFile(this,"org.doit.canvas.demo.fileprovider",getPhotoFile());
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT,fileUri);
List<ResolveInfo> resolveInfoList = getPackageManager().queryIntentActivities(captureIntent,PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo:resolveInfoList){
grantUriPermission(resolveInfo.activityInfo.packageName,fileUri,Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
startActivityForResult(captureIntent,REQ_CAPTURE_PHOTO);
}
}
private File getPhotoFile(){
File parentFile = getFilesDir();
return new File(parentFile,"capture_1.jpg");
}
上述代码中,使用隐式Intent,MediaStore.ACTION_IMAGE_CAPTURE进行拍照。首先检查手机中是否有Camera应用,以免调用出现错误。接着我们获取应用的私有目录,并使用FileProvider将目录转化为Uri并使用MediaStore.EXTRA_OUTPUT重定向照片的存储位置。最后对Camera应用使用grantUriPermission()进行Uri写入的授权操作。由于手机中的Camera应用可能不止一个,还可能有美颜,美图之类的第三方应用,所以我们需要对所有Camera应用进行授权。
在onActivityResult回调函数中:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQ_TAKE_PHOTO){
Bitmap bitmap = Utils.getScaleBitmap(getPhotoFile().getPath(),400,400);
mImageView.setImageBitmap(bitmap);
Uri fileUri = FileProvider.getUriForFile(this,"org.doit.canvas.demo.fileprovider",getPhotoFile());
revokeUriPermission(fileUri,Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
}
public static Bitmap getScaleBitmap(String path,int destHeight,int destWidth){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(path,options);
int originalWidth = options.outWidth;
int originalHeight = options.outHeight;
int inSampleSize = 1;
if (originalHeight > destHeight || originalWidth > destWidth){
float scaleWidth = originalWidth / destWidth;
float scaleHeight = originalHeight / destHeight;
inSampleSize = Math.round(scaleHeight>scaleWidth? scaleHeight:scaleWidth);
}
options.inSampleSize = inSampleSize;
options.inJustDecodeBounds=false;
return BitmapFactory.decodeFile(path,options);
}
在代码中,我们获取拍摄的图片之后对图片进行了处理之后进行显示,如果处理部分的代码看不懂的话,
点击阅读此博客。图片显示之后,需要使用revokeUriPermission取消去应用的Uri写入权限。
具体可以阅读一下博客: Android 7.0 行为变更 通过FileProvider在应用间共享文件吧