系统功能的调用
在开发的应用中调用系统现有应用,需要使用Intent指定开启的应用的Action和Category,然后通过startActivity(Intent)或者startActivityForResult(Intent,int)开启指定的Activity,如果使用startActivityForResult()方法开启并需要返回值,再重写onActivityResult(int,int,Intent)即可。
权限
1 2 3 public class MainActivity extends AppCompatActivity {Button btn1,btn2,btn3,btn4;
VideoView videoView;
ImageView imageView;
private static final int VIDEO = 1001;
private static final int IMAGE = 1002;
String path;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT > 23){
int i = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
if (i == PackageManager.PERMISSION_DENIED){
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CALL_PHONE},101);
}
}
btn1 = findViewById(R.id.browser);
btn2 = findViewById(R.id.phone);
btn3 = findViewById(R.id.video);
btn4 = findViewById(R.id.camera);
imageView = findViewById(R.id.photo);
videoView = findViewById(R.id.vv);
//网页跳转
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://www.baidu.com"));
startActivity(intent);
}
});
//打电话
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:"+"18360178160"));
startActivity(intent);
}
});
//录像
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult(intent,VIDEO);
}
});
//拍照
btn4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
//将照片存储到手机中
//生成图片的名字
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
String name="IMG_"+year+(month+1)+day+"_"+hour+minute+second+".jpg";
path="/sdcard/DCIM/Camera/"+name;
//使用内容提供者向图库插入一条记录
ContentResolver contentResolver = getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Images.Media.DATA,path);//图片路径
Uri uri=contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
intent.putExtra(MediaStore.EXTRA_OUTPUT,uri);
startActivityForResult(intent,IMAGE);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == VIDEO && resultCode == Activity.RESULT_OK){
Uri uri = data.getData();
videoView.setVideoURI(uri);
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
videoView.start();
}
});
}else if (requestCode == IMAGE && resultCode == Activity.RESULT_OK){
Bitmap bitmap = BitmapFactory.decodeFile(path);
imageView.setImageBitmap(bitmap);
}
}
}
FileProvider
关于 FileProvider
官方对于 FileProvider 的解释为:FileProvider 是一个特殊的 ContentProvider 子类,通过 content://Uri 代替 file://Uri 实现不同 App 间的文件安全共享。
当通过包含 Content URI 的 Intent 共享文件时,需要申请临时的读写权限,可以通过 Intent.setFlags() 方法实现。而 file://Uri 方式需要申请长期有效的文件读写权限,直到这个权限被手动改变为止,这是极其不安全的做法。因此 Android 从 N 版本开始禁止通过 file://Uri 在不同 App 之间共享文件。
FileProvider 的使用流程
1.定义一个 FileProvider
2.指定有效的文件
3.为文件生成有效的 Content URI
4.申请临时的读写权限
定义 FileProvider
1.设置 android:name 为android.support.v4.content.FileProvider,这是固定的,不需要手动更改;
2.设置 android:authorities 为 uri;
3.设置 android:exported 为 false ,表示 FileProvider 不是公开的;
4.设置 android:grantUriPermissions 为 true 表示允许临时读写文件。
注意
1.android:authorities 最好是 application id 而不能直接用包名硬编码,因为 Android 系统要求 android:authorities 对于每个 App 而言必须是唯一的。
2.假如 FileProvider 用在 SDK 中,多个 App 都在调用同一个 SDK,而 SDK 中的 android:authorities 为硬编码,那么 App 之间的 authorities 就会出现冲突,会报 Install shows error in console: INSTALL FAILED CONFLICTING PROVIDER 的错误。
3.如果 SDK 的 android:authorities 是 application id,那么 authorities 会和宿主 App 的 application id 保持一致,就不会出现 authorities 冲突的问题。
4.在 Java 代码中调用 getPackageName() 返回的是 application id ,而非 package name ,要验证这一点也很容易,在 build.gradle 文件中定义和包名不同的 application id ,打印代码中 getPackageName() 的返回值,就会发现返回值是 build.gradle 中自定义的 application id ,而非 package name
5.关于 package name 和 application id 的区别:application id 负责 App 的进程 ID;package name 负责 R 的包名以及 Manifest 中 Activity 等四大组件的相对包名。如果 build.gradle 中没有指定 applicationId,那么 application id 的默认值就是 manifest 的 package 属性值。
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--authorities:uri name:名字写死 exported:只能被app访问 grantUriPermissionss:授予权限-->
<provider
android:exported="false"
android:grantUriPermissions="true"
android:authorities="com.practice.prov"
android:name="android.support.v4.content.FileProvider">
<!--meta-data fileprovider操作的文件的路径 name:名字 写死 resource:xml文件定义路径-->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths"></meta-data>
</provider>
res中新建"xml"文件夹,创建paths文件
<?xml version="1.0" encoding="utf-8"?>activity
/**
-
打开照相机,不能自动保存图片,使用FileProvider保存
-
1.清单文件直接注册provider(这个provider不是我们写的,系统和自带的)
-
2.定义xml:文件路径
-
3.使用内容提供者:Uri uri=FileProvider.getUriForFile(); intent.putEtra();
-
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {private Button bt_browser;
private Button bt_call;
private Button bt_video;
private Button bt_camera;
private ImageView iv;
private VideoView vv;
public static final int VIDEO_CODE = 101;
public static final int IMAGE_CODE = 102;
String path;
private Button bt_jie;@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}private void initView() {
bt_browser = (Button) findViewById(R.id.bt_browser);
bt_call = (Button) findViewById(R.id.bt_call);
bt_video = (Button) findViewById(R.id.bt_video);
bt_camera = (Button) findViewById(R.id.bt_camera);
iv = (ImageView) findViewById(R.id.iv);
vv = (VideoView) findViewById(R.id.vv);bt_browser.setOnClickListener(this); bt_call.setOnClickListener(this); bt_video.setOnClickListener(this); bt_camera.setOnClickListener(this); bt_jie = (Button) findViewById(R.id.bt_jie); bt_jie.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_browser: //打开系统浏览器
browser();
break;
case R.id.bt_call: //打电话
call();
break;
case R.id.bt_video: //打开摄像机
video();
break;
case R.id.bt_camera: //打开照相机
camera();
break;
case R.id.bt_jie:
jietu();
break;
}
}private void jietu() {
View decorView = getWindow().getDecorView();
decorView.setDrawingCacheEnabled(true);//设置可以缓存
decorView.buildDrawingCache();//缓存一下,截图
Bitmap bitmap = decorView.getDrawingCache();//得到截图
iv.setImageBitmap(bitmap);
//将图片缓存到SD卡中
try {
//参数一 格式 参数二 质量 参数三 SD卡输出流
String createname = createname();
bitmap.compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream("/sdcard/DCIM/Camera/"+createname));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public String createname(){
//IMG_20190716_160050.png
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int date = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR);
int min = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
String filename=“IMG_”+year+(month+1)+date+"_"+hour+ min+second+".png";
return filename;
}
private void video() {//打开摄像机
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);//设置频道
startActivityForResult(intent, VIDEO_CODE);
}private void camera() {//打开照相机
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置频道//TODO 1:使用FileProvider向手机插入一条记录 String createname = createname(); File file = new File("/sdcard/DCIM/Camera/"+createname); //根据file得到uri并且使用内容提供者插入了一条记录 Uri uri = FileProvider.getUriForFile(this, "com.practice.prov", file); //TODO 2:将照片保存到SD卡中 intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, IMAGE_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//requestCode 请求码 resultcode 结果码 data 数据包含摄像后视频的路劲
if (requestCode == VIDEO_CODE && resultCode == Activity.RESULT_OK) {
Uri uri = data.getData();//视频uri路径
Toast.makeText(this, “视频:” + uri, Toast.LENGTH_SHORT).show();
//放到videoview播放
vv.setVideoURI(uri);//设置资源
vv.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
vv.start();//启动
}
});
} else if (requestCode == IMAGE_CODE && resultCode == Activity.RESULT_OK) {
//获得SD卡图片
Bitmap bitmap = BitmapFactory.decodeFile(path);
iv.setImageBitmap(bitmap);
}}
private void call() {
//打电话
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);//设置频道
intent.setData(Uri.parse(“tel:” + “18630704579”));
startActivity(intent);
}private void browser() {
//打开系统浏览器
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);//设置频道
Uri uri = Uri.parse(“https://www.baidu.com”);
intent.setData(uri);
startActivity(intent);
}
}