第八章 多媒体的使用
-
通知的使用
-
首先需要获取NotificationManager对通知进行管理
-
NotificationManager manager = getSystemService(Context.NOTIFICATION_SERVICE);
-
-
使用support库中 提供的NotificationCompat类来创建notification的对象
-
Notification notification = NotificationCompat
.Builder(context)
.setContentTitle("XXXXX00")
.setContentText("xxxxxxx")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.small_icon)
.setLargeIcon(BitMapFactory.decodeResource(
getResource(),
R.drawable.large_icon))
.build();
-
-
调用NotificationManager 的 notify方法让通知显示
-
参数1:id,需要每个通知的id都不一样
-
参数2:刚刚创建的notification的对象
-
-
PendingIntent的使用,用于响应用户点击通知事件
-
创建PendingIntent对象:PengdingIntent.getActivity(this,0,intent,0);
-
其中this是context上下文,intent是启动活动的意图,另外两个参数填入0就可以了
-
然后通过在创建notification对象的时候.setContentIntent(pi)传入这个pendingIntent对象
-
-
-
点击通知后取消
-
默认是不会取消通知的,需要在创建notification的时候setAutoCancel(true)或者在新开启的活动或者广播或者服务中调用NotificationManager 对象的cancel(ID) 来手动取消,这里的ID是通知的ID
-
-
通知的高级技巧
-
.....主要是一些在通知中显示长文本或者显示图片等技巧
-
-
-
摄像头和相册
-
从照相机获取图片
//从摄像头获取图片 //新建一个图片文件,路径是sd卡中的缓存目录 File outputImage = new File(getExternalCacheDir(), "output_image.jpg"); try { //如果文件已经存在则删除并重新创建一个新文件 if (outputImage.exists()) { outputImage.delete(); } outputImage.createNewFile(); } catch (IOException e) { e.printStackTrace(); } //这里可能是不同SDK的api不兼容的文件,区分24上下的api,作用是获取图片文件的资源定位,相当于指针,通过uri就可以安全访问这个文件 if (Build.VERSION.SDK_INT>=24){ imageUri = FileProvider.getUriForFile(MainActivity.this, "com.hrh.cameraalbumtest.fileprovider", outputImage); }else{ imageUri = Uri.fromFile(outputImage); } //创建一个intent意图,通过action指明要打开照相机的活动,并且通过putExtra指定了照相机的捕获结果存放在外部文件,路径是uri,指向了图片文件,然后打开活动。 Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri); startActivityForResult(intent,TAKE_PHOTO);
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode){ case TAKE_PHOTO: if (resultCode == RESULT_OK){ try { //当回调方法被调用时,图片已经被加载到那个图片文件中,通过uri访问这个文件,并得到输入流交给位图工厂解析得到位图对象,这样imageView可以通过位图对象来显示拍摄的结果. Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri)); picture.setImageBitmap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } } break; default: break; } }
因为用到了fileProvider 需要在manifest中配置
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> ... <provider android:authorities="com.hrh.cameraalbumtest.fileprovider" android:name="androidx.core.content.FileProvider" android:exported="false" android:grantUriPermissions="true" > <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> ... </application>
其中meta-data中的resource是配置provider能够访问到的文件目录范围,fileprovider通过给定的file文件对象的文件路径来找到对应的图片文件,并将它封装为uri对象返回,因此这个文件的路径一定要被provider访问到,但是有时候会发生未知的错误
@xml/fiile_paths
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <root-path name="my_images" path=""/> </paths>
在这里 root-path表示整个应用的根目录,虽然他不推荐使用但是这里不这样做就找不到文件,还有其他选项例如 files-path对应的目录是getFilesDir的目录,cache-path对应的目录是getCacheDir等等。
-
从相册获取图片
-
访问相册属于危险权限,需要进行动态运行时权限申请,代码如下,openAlbum是自定义的打开相册的方法
if (ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1); }else{ openAlbum(); }
-
申请权限对应的回调方法为onRequestPermissionsResult,代码如下
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode){ case 1: if (grantResults.length>0&&(grantResults[0] == PackageManager.PERMISSION_GRANTED)){ openAlbum(); }else{ Toast.makeText(this,"you denied the permission",Toast.LENGTH_SHORT).show(); } break; default: } }
-
如果用户接受授权,接下来是打开相册的方法,openAlbum:
private void openAlbum() { Intent intent = new Intent("android.intent.action.GET_CONTENT"); intent.setType("image/*"); startActivityForResult(intent,CHOOSE_PHOTO); }
-
对应的启动活动并返回结果的回调是onActivityResult,代码如下:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { //super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { ... case CHOOSE_PHOTO: if (resultCode == RESULT_OK) { if (data != null) { handleImageOnKitKat(data); //handleImageBeforeKitKat(data); } } default: break; } }
-
由于在安卓系统7.0之后打开相册返回的Intent data中,通过Uri getData()得到的uri对象不是真实的uri,也就是说无法通过这个uri对象直接访问图片文件,需要经过解析才能得到真实的uri,解析的代码不是很懂,有点复杂,代码如下:
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.parseLong(docId)); imagePath = getImagePath(contentUri,null); } }else if ("content".equalsIgnoreCase(uri.getScheme())){ imagePath = getImagePath(uri,null); }else if ("file".equalsIgnoreCase(uri.getScheme())){ imagePath = uri.getPath(); } displayImage(imagePath); }
具体是通过判断uri的不同类型进行重新包装,然后调用自定义的getImagePath和displayImage方法来展示图片,这两代码如下:
private String getImagePath(Uri uri,String selection){ String path = null; 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,"fail to get image",Toast.LENGTH_SHORT).show(); } }
-
-
播放音频
-
MediaPlayer类的使用
-
创建MediaPlayer的对象
-
调用setDataSource方法设置音频的路径
-
调用prepare进行播放的准备工作
-
调用start开始播放音频
-
调用pause暂停播放
-
调用stop停止播放
-
调用reset重置
-
调用getDuration获取音频的时长
-
最后释放资源需要调用stop方法和release方法
-
-
使用之前需要动态申请权限
-
不需要在布局中创建布局
-
-
播放视频
-
VideoView类的使用
-
需要添加布局 < VideoView id="video_view" />
-
很多方法和mediaPlayer都很类似
-
最后释放资源的方法是suspend,和mediaplayer不一样
-
-