Android通知怎么实现?Android开发如何操作相机和相册?

  • 前言
  • 八、Android通知怎么实现?Android开发如何操作相机和相册?
  • 8.1 通知介绍
  • 8.2 通知的基本用法
  • 8.3 Android调用相机和相册
  • 8.3.1 调用相机拍照
  • 8.3.2 调用相册,查看照片
  • 参考书籍:第一行代码


前言

本文讲解Android开发中通知的基本用法,以及如何对手机中最常用的相机和相册进行调用。

八、Android通知怎么实现?Android开发如何操作相机和相册?

8.1 通知介绍

一个应用程序不在前台,但是又想给用户发送消息,该怎么办?解决办法就是使用通知,具体效果就是在状态栏弹出一条消息。

8.2 通知的基本用法

通知的使用非常简单,Android提供NotificationManager类管理通知,通过notify方法发出通知,notify方法需要传入一个唯一的通知ID,和具体的通知内容Notification。

核心示例代码如下:

//1. 获取通知管理类
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        
        //2. 版本稳定性控制
        String channelID="001";
        String channelName="channel1";
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            //参数1:channel的ID; 参数2:channel的name:; 参数3:通知Channel的级别(重要程度)
            NotificationChannel notificationChannel = new NotificationChannel(channelID, channelName, NotificationManager.IMPORTANCE_LOW);
            manager.createNotificationChannel(notificationChannel);
        }
        
        //3. 点击通知会转到的“意图”(Intent更倾向于立即执行某个动作,而PendingIntent是倾向在合适的时机去执行某个动作)
  		Intent intent = new Intent(this, NotificationActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
        
        //4. 构造具体的通知对象
        Notification notification = new NotificationCompat.Builder(this,channelID)
                .setContentTitle("我发送的消息通知")
                //可显示完整的大量文字
                //.setStyle(new NotificationCompat.BigTextStyle().bigText("请注意查看这条消息请注意查看这条消息请注意查看这条消息请注意查看这条消息请注意查看这条消息请注意查看这条消息请注意查看这条消息请注意查看这条消息请注意查看这条消息"))
                //.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_background)))
                .setContentText("请注意查看这条消息")//过长的文字会用...表示
                .setWhen(System.currentTimeMillis())//指定通知被创建的时间以毫秒为单位
                .setSmallIcon(R.mipmap.ic_launcher)//指定通知在状态栏显示的小图标
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))//指定下拉通知后,在状态栏显示的大图标
                .setAutoCancel(true)//看过通知,取消图标
                .setContentIntent(pendingIntent)//点击通知,跳转页面
                .setSound(Uri.fromFile(new File("/system/media/audio/notifications/Bubble.ogg")))//设置通知声音
                .setVibrate(new long[]{0,1000,1000,1000})//静止0s,振动1s,静止1s,振动1s
                .setDefaults(NotificationCompat.DEFAULT_ALL)//设置系统默认的声音,震动等效果
                .setPriority(NotificationCompat.PRIORITY_MAX)//设置通知的优先级(重要程度)
                .build();

        //5. 发送通知
        manager.notify(1,notification);

8.3 Android调用相机和相册

在讲解Android四大组件–活动(Activity)的时候,我们讲了两种活动之间跳转的方法,一种是显示Intent,一种是隐式Intent,当时我们就说了,隐式Intent可以实现跳转到别的程序,那么这一节调用相机和相册就是用隐式Intent实现的。

8.3.1 调用相机拍照

  1. 调用相机,就是从当前程序跳转到相机,隐式Intent实现示例代码如下:
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT,imgUri);
startActivityForResult(intent,TAKE_PHONE);

上面的代码可以拉起系统的相机,但是拍照就需要指定照片存放的位置,因此intent.putExtra指定照片的输出位置,但是Android中照片的位置需要用URI表示,已知照片的File对象,如何获取该文件的URI呢?

  1. Android中有一个内容提供器类FileProvider,可以将File转为URI

代码示例如下:

File outImgFile =  new File(getExternalCacheDir(), "out.jpg");
//参数1:Context; 参数2:在AndroidManifest.xml文件中配置的authority; 参数3:待转换的File
Uri imgUri= FileProvider.getUriForFile(MainActivity.this,"com.xiaomi.cameraalbumtest.fileprovider",outImgFile);
  1. 因为要用FileProvider内容提供器,我们就要在AndroidManifest.xml中注册该提供器,注册配置如下:
<provider
	android:authorities="com.xiaomi.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>
  1. 既然是内容提供器,就要指定那些数据可以被访问,上面resouce指定的文件就定义了那些数据可以访问,file_paths内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="my_images" <!--这个名字可以随便命名-->
        path="Android/data/com.xiaomi.cameraalbumtest/cache"/> <!--可以被访问的路径-->
</paths>
  1. 通过以上步骤,就可以调用系统相机拍照,并将照片保存起来,照片的Uri就是通过FileProvider内容提供器获得的imgUri,通过照片Uri获取照片Bitmap对象的代码如下:
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imgUri));

8.3.2 调用相册,查看照片

  1. 启动相册与启动相机类似,都是通过隐式Intent实现,示例代码如下:
Intent intent=new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent,CHOOSE_PHOTO);
  1. 在回调函数中获取打开图片的Uri
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        String imgPath=null;
        Uri uri = data.getData();
}
  1. 通过Uri获取照片的实际路径的代码如下
private String UriToPath(Uri uri) {
        String s = uri.getScheme()+"://" + uri.getAuthority() + uri.getPath() +"/"+ uri.getPathSegments();
        if (DocumentsContract.isDocumentUri(this,uri))
        {
            String docId=DocumentsContract.getDocumentId(uri);//image:1000000050
            if ("com.android.providers.media.documents".equals(uri.getAuthority()))
            {
                String id = docId.split(":")[1];
                String selection = MediaStore.Images.Media._ID + "=" + id;
                imgPath=getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection);//相册图片的路径存储在程序com.android.providers.media.documents的数据库中的表document中
            }
            else if ("com.android.providers.downloads.documents".equals(uri.getAuthority()))
            {
                Uri contentUri= ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),Long.valueOf(docId));
                imgPath=getImagePath(contentUri,null);
            }
        }
        else if ("content".equalsIgnoreCase(uri.getScheme()))
        {
            imgPath=getImagePath(uri,null);
        }
        else if ("file".equalsIgnoreCase(uri.getScheme()))
        {
            imgPath=uri.getPath();
        }
        return imgPath;
    }
  1. 有了图片的路径,我们就能对其进行展示等操作。

参考书籍:第一行代码

链接:https://pan.baidu.com/s/1aXtOQCXL6qzxEFLBlqXs1Q?pwd=n5ag
提取码:n5ag