当前位置: 首页 > news >正文

【Android】安卓多媒体之通知、摄像头、相册、播放音乐、视频用法总结

文章目录

  • 一、通知
    • 1. 申请权限
    • 2. 创建通道
    • 3. 创建通知
    • 4. 发送通知
    • 拓展功能
      • 点击行为
      • 更新通知
      • 取消通知
      • 锁屏通知
      • 富文本通知
  • 二、摄像头
    • 1. 申请权限
    • 2. 调用逻辑
    • 3. 声明内容提供器
  • 三、打开相册
    • 1. 申请权限
      • 检查并请求权限
      • 处理权限请求结果
    • 2.处理图片
      • 从相册中选择图片
      • 处理选择图片的结果
      • 处理图片
      • 获取图片真实路径
  • 四、播放音乐
    • 1.申请权限
    • 2.处理音乐
    • MediaPlayer
  • 五、播放视频
    • 方法
    • 属性
    • 示例

一、通知

Android 8.0(API26)后对通知更改了一些内容,以前是通过Notification,Builder(Context context).se..来设置通知的震动、灯光、音效的设置,新内容加了NotificationChannel(通知渠道),通过NotificatonChannel来进行震动、灯光、音效的设置,且通知必须添加通知渠道,同样需进行版本判断,否则通知不会被发送。

步骤:

  1. 首先创建NotificationManager对象
  2. 创建Notificationchannel对象
  3. 通过Notificationcompat.Builder(Context.Notification)对象指定channel并设置通知的各项信息,调用build()方法创建Notifcation对象
  4. 调用NotificationManagernotify(id,Notification)方法发送通知

1. 申请权限

AndroidManifest.xml 文件中声明权限

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

在运行时请求权限

if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)!= PackageManager.PERMISSION_GRANTED) {// 权限尚未授予,申请权限ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.POST_NOTIFICATIONS},1);
}

2. 创建通道

使用NotificationChannel类创建通知通道的实例
创建通知通道:

  • 设置唯一的id
  • 通道的用户可见的名称
  • 通道的重要性

image-20240731095312726

private static final String MESSAGES_CHANNEL = "default_channel";
private void createMessagesNotificationChannel(Context context) {// 检查当前设备的系统版本是否大于或等于 Android 8.0 (API 级别 26)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {// 从资源中获取通知渠道的名称CharSequence name = context.getString(R.string.message_channel_name);// 创建一个通知渠道对象NotificationChannel channel = new NotificationChannel(MESSAGES_CHANNEL, // 渠道 ID,用于标识这个通知渠道name, // 渠道名称,从资源文件中获取NotificationManager.IMPORTANCE_HIGH // 渠道的重要性级别,决定通知的行为和显示方式);// 获取 NotificationManager 系统服务NotificationManager manager = context.getSystemService(NotificationManager.class);// 创建通知渠道manager.createNotificationChannel(channel);}
}

这样后就创建了渠道,下来直接构建通知然后发送即可

3. 创建通知

image-20240731095422811

    public void onClick(View v) {NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);Notification notification = new NotificationCompat.Builder(this, MESSAGES_CHANNEL).setContentTitle("重要通知").setContentText("您今天睡眠时间不足").setWhen(System.currentTimeMillis()).setSmallIcon(R.drawable.messages_1).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.messages_2)).build();manager.notify(1, notification);}

4. 发送通知

使用NotificationManager类发送通知

  • 调用getSystemService()方法创建NotificationManager的对象
  • 调用它的notify()方法发送消息,传递通知idNotification对象
 manager.notify(1, notification); // 参数 1 是通知的 ID,用于更新或取消通知,notification 是要显示的通知对象

拓展功能

点击行为

所有通知在点击后都必须作出响应,一般是启动一个Activity

  • 调用setContentlntent()方法设置一个内容Intent;

  • 然后通过一个PendingIntent对象传递内容Intent

public void onClick(View v) {//----在这里设置PendingIntent----Intent intent = new Intent(this, NotificationActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_IMMUTABLE);NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);Notification notification = new NotificationCompat.Builder(this, MESSAGES_CHANNEL).setContentTitle("重要通知").setContentText("您今天睡眠时间不足").setWhen(System.currentTimeMillis()).setSmallIcon(R.drawable.messages_1).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.messages_2)).setContentIntent(pendingIntent)// 设置点击通知时的 PendingIntent.setAutoCancel(true)// 点击通知后自动取消.build();manager.notify(1, notification);}
public static PendingIntent getActivity
(Context context, int requestCode, Intent intent, int flags)

PendingIntent 是一种封装了 Intent 的机制,可以在将来某个时刻代替应用程序的进程执行特定的操作,即使应用程序不在运行中。

flags: 标志位,指定 PendingIntent 的行为。常用标志包括:

通常使用FLAG_IMMUTABLE

  • PendingIntent.FLAG_UPDATE_CURRENT: 如果 PendingIntent 已存在,更新其内容。
  • PendingIntent.FLAG_CANCEL_CURRENT: 如果 PendingIntent 已存在,先取消它,然后创建一个新的。
  • PendingIntent.FLAG_IMMUTABLE: 使 PendingIntent 不可变,即创建后不会被修改。
  • PendingIntent.FLAG_MUTABLE: 使 PendingIntent 可变,即创建后可以被修改。

更新通知

  • 使用NotificationCompat.Builder构造其创建有更新内容的通知
  • 将相同的通知Id和更新内容后的通知传递给notify()方法即可实现更新
    • 若之前的通知仍然可见,则系统更新
    • 若之前的通知已被取消,则发送新的通知

取消通知

通知会一直保存可见,以下操作会使消息取消

  • 用户通过滑动或使用"清除所有"取消它
  • 创建通知时调用setAutoCancel(),那么当用户单击通知时会从状态栏消失
  • 通过NotificationManagercancel(通知ld)取消,或调用cancelAll()取消所有通知

锁屏通知

Android 5.0(APl21)开始,通知可以显示在锁屏上。用户可以通过设置选择是否允许敏感的通知内容显示在安全的锁屏上。

android5.0加入一种新的模式Notification的显示等级,共有三种:

  • VISIBILITY_PUBLIC 任何情况都会显示通知
  • VISIBILITY_PRIVATE 显示基本信息隐藏通知内部信息
  • VISIBILITY SECRET 在没有锁屏的情况下才能够显示
  • 调用setVisibility方法设置
builder.setVisibility(Notification.VISIBILITY_PUBLIC);

富文本通知

富文本通知指的是可以展示复杂内容的通知,例如包含多种样式的文本、图片、链接等。要创建富文本通知,可以使用 NotificationCompat 类的一些方法和样式。

setStyle(new NotificationCompat.BigTextStyle())
  1. 使用 BigTextStyleBigTextStyle 用于显示大段文本内容,这些内容会在展开时显示完整。
        Notification notification = new NotificationCompat.Builder(this, MESSAGES_CHANNEL).setContentTitle("富文本通知").setContentText("点击查看详细内容").setWhen(System.currentTimeMillis()).setSmallIcon(R.drawable.messages_1).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.messages_2)).setStyle(new NotificationCompat.BigTextStyle().bigText("这是一个长文本示例。在展开通知后,可以看到更多的内容," +"而不是只显示简短的预览文本。这样可以展示更详细的信息。")).setContentIntent(pendingIntent).setAutoCancel(true).build();

VID_20240731_115043

  1. 使用 BigPictureStyleBigPictureStyle 用于显示一张大图片,可以同时显示文本。

  2. 使用 InboxStyleInboxStyle 用于显示一组消息的列表,适合显示多个简短的消息。

  3. MessageingStyle通知

使用 MessagingStyle 的通知可以展示一系列的消息,仿佛是一个对话线程,让用户能够在通知栏中查看消息交流的上下文。

// 创建 MessagingStyle 对象NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle("聊天机器人").addMessage("你好!有什么我可以帮助你的吗?", System.currentTimeMillis(), "聊天机器人") 
// 添加一条消息,内容为“你好!有什么我可以帮助你的吗?”,时间为当前时间,发送者为“聊天机器人”.addMessage("我想知道今天的天气怎么样。", System.currentTimeMillis(), "用户") 
// 添加另一条消息,内容为“我想知道今天的天气怎么样。”,时间为当前时间,发送者为“用户”.setConversationTitle("天气咨询"); 
// 设置对话标题为“天气咨询”,用来标识对话的主题// 创建通知Notification notification = new NotificationCompat.Builder(this, MESSAGES_CHANNEL).setContentTitle("消息通知").setContentText("您有新的消息").setWhen(System.currentTimeMillis()).setSmallIcon(R.drawable.messages_1).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.messages_2)).setStyle(messagingStyle) // 设置 MessagingStyle.setContentIntent(pendingIntent) .setAutoCancel(true) .build();manager.notify(1, notification);}

Screenshot_2024-07-31-11-43-50-051_com.android.sy

二、摄像头

1. 申请权限

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

允许应用使用设备的相机进行拍照或录像

在运行时请求权限

public class MainActivity extends AppCompatActivity {private ImageView image;  // 显示拍摄照片的ImageViewprivate static final int REQUEST_CAMERA_PERMISSION = 100;  // 请求权限的请求码@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);image = findViewById(R.id.image);// 检查并请求相机权限if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);}}// 处理权限请求结果@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == REQUEST_CAMERA_PERMISSION) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 权限授予,执行相应操作} else {// 权限拒绝,提示用户Toast.makeText(this, "相机权限被拒绝", Toast.LENGTH_SHORT).show();}}}

2. 调用逻辑

public class MainActivity extends AppCompatActivity {private ImageView image;  // 显示拍摄照片的ImageViewprivate Uri imageUri;  // 存储照片文件的Uriprivate static final int TAKE_PHOTO = 1;  // 拍照请求码private static final int REQUEST_CAMERA_PERMISSION = 100;  // 请求权限的请求码@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);image = findViewById(R.id.image);// 检查并请求相机权限if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);}}// 处理权限请求结果@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == REQUEST_CAMERA_PERMISSION) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 权限授予,执行相应操作} else {// 权限拒绝,提示用户Toast.makeText(this, "相机权限被拒绝", Toast.LENGTH_SHORT).show();}}}// 调用相机拍照public void invokeCamera(View view) {// 创建一个文件对象,用于存储拍摄的照片,存储在应用的外部缓存目录中,文件名为 "output_image.jpg"File outputImage = new File(getExternalCacheDir(), "output_image.jpg");try {// 如果文件存在,删除旧文件if (outputImage.exists()) {outputImage.delete();}// 创建新文件outputImage.createNewFile();} catch (IOException e) {// 处理文件操作异常throw new RuntimeException(e);}// 检查安卓版本,如果版本大于等于 24(安卓 7.0),使用 FileProvider 获取文件的 URIif (Build.VERSION.SDK_INT >= 24) {// FileProvider 是一个安全的方式来分享文件imageUri = FileProvider.getUriForFile(MainActivity.this, "com.example.cameraalubmtest.fileprovider", outputImage);} else {// 如果安卓版本小于 24,直接获取文件的 URIimageUri = Uri.fromFile(outputImage);}// 创建一个 Intent 对象,指定动作为 "android.media.action.IMAGE_CAPTURE" 以调用系统相机应用Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");// 将文件 URI 作为额外参数传递给相机应用,指定拍摄的照片应保存到该 URI 对应的文件中intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);// 启动相机应用,并传入请求码 TAKE_PHOTO,等待返回结果startActivityForResult(intent, TAKE_PHOTO);}// 处理拍照结果@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);switch (requestCode) {case TAKE_PHOTO:if (resultCode == RESULT_OK) {try {// 使用内容解析器打开 imageUri 对应的输入流,并将其解码为 BitmapBitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));// 将解码后的 Bitmap 设置为 ImageView 的图像显示image.setImageBitmap(bitmap);} catch (FileNotFoundException e) {// 如果文件未找到,抛出运行时异常throw new RuntimeException(e);}}break;default:break;}}

3. 声明内容提供器

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.CameraAlubmTest"tools:targetApi="31"><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><providerandroid:name="androidx.core.content.FileProvider"android:authorities="com.example.cameraalubmtest.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" /></provider></application>
</manifest>

指定路径配置文件的位置:

新建file_paths.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android"><external-pathname="my_images"path="." />
</paths>

三、打开相册

1. 申请权限

检查并请求权限

onCreate 方法中,应用检查相机和存储权限是否已经被授予。如果未被授予,则请求这些权限。

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED|| ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION);
}

这里用到的 ContextCompat.checkSelfPermission 方法返回一个整数,表示指定权限是否被授予。如果返回值为 PackageManager.PERMISSION_GRANTED,则表示权限已被授予;否则表示未被授予。

如果任何一个权限未被授予,则通过 ActivityCompat.requestPermissions 方法请求这些权限。请求码 REQUEST_CAMERA_PERMISSION 用于在权限请求结果中识别这个请求。

处理权限请求结果

当用户响应权限请求时,系统会调用 onRequestPermissionsResult 方法。在这里处理用户的响应。

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode) {case REQUEST_CAMERA_PERMISSION:if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 权限授予,执行相应操作} else {// 权限拒绝,提示用户Toast.makeText(this, "相机权限被拒绝", Toast.LENGTH_SHORT).show();}}
}

在这个方法中,我们检查请求码是否为 REQUEST_CAMERA_PERMISSION,然后检查 grantResults 数组,确认权限是否被授予。如果权限被拒绝,我们通过 Toast 提示用户权限被拒绝。

2.处理图片

从相册中选择图片

public void chooseFromAlbum(View view) {// 创建一个 Intent 对象,用于启动系统的图片选择器Intent intent = new Intent("android.intent.action.GET_CONTENT");// 设置选择器类型为图片intent.setType("image/*");// 启动图片选择器,并传入请求码 CHOOSE_PHOTO,等待返回结果startActivityForResult(intent, CHOOSE_PHOTO);
}

处理选择图片的结果

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);switch (requestCode) {case TAKE_PHOTO:// 拍照case CHOOSE_PHOTO:if (resultCode == RESULT_OK) {if (Build.VERSION.SDK_INT >= 19) {// 针对安卓 4.4 及以上系统处理图片handleImageOnKitKat(data);} else {// 针对低版本安卓系统处理图片}}break;default:break;}
}

处理图片

@TargetApi(19)
private void handleImageOnKitKat(Intent data) {String imagePath = null;// 获取用户选择的图片的 URIUri 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())) {// 如果是媒体类型的 Document Uri,解析出数字 IDString 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())) {// 如果是下载类型的 Document Uri,解析出文件 IDUri 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())) {// 如果是 file 类型的 Uri,直接获取图片路径imagePath = uri.getPath();}// 显示图片displayImage(imagePath);
}

获取图片真实路径

@SuppressLint("Range")
private String getImagePath(Uri uri, String selection) {String path = null;// 通过内容解析器查询指定 URI 的数据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;
}

四、播放音乐

image-20240801121942815

1.申请权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
public class MainActivity extends AppCompatActivity implements View.OnClickListener {private static final int REQUEST_PERMISSION_CODE = 1; // 权限请求代码private MediaPlayer mediaPlayer = new MediaPlayer(); // 媒体播放器实例@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main); // 设置布局文件// 初始化按钮并设置点击监听器Button btn1 = findViewById(R.id.btn_start);Button btn2 = findViewById(R.id.btn_pause);Button btn3 = findViewById(R.id.btn_stop);btn1.setOnClickListener(this);btn2.setOnClickListener(this);btn3.setOnClickListener(this);// 检查是否具有读取外部存储的权限if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {// 请求权限ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_PERMISSION_CODE);} else {// 已有权限,初始化媒体播放器initMediaPlayer();}}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == REQUEST_PERMISSION_CODE) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 权限被授予,初始化媒体播放器initMediaPlayer();} else {// 权限被拒绝,显示提示并关闭应用Toast.makeText(this, "拒绝权限将无法使用程序", Toast.LENGTH_SHORT).show();finish();}}}
}

2.处理音乐

public class MainActivity extends AppCompatActivity implements View.OnClickListener {private static final int REQUEST_PERMISSION_CODE = 1; // 权限请求代码private MediaPlayer mediaPlayer = new MediaPlayer(); // 媒体播放器实例@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main); // 设置布局文件// 初始化按钮并设置点击监听器Button btn1 = findViewById(R.id.btn_start);Button btn2 = findViewById(R.id.btn_pause);Button btn3 = findViewById(R.id.btn_stop);btn1.setOnClickListener(this);btn2.setOnClickListener(this);btn3.setOnClickListener(this);// 检查是否具有读取外部存储的权限if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {// 请求权限ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_PERMISSION_CODE);} else {// 已有权限,初始化媒体播放器initMediaPlayer();}}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == REQUEST_PERMISSION_CODE) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 权限被授予,初始化媒体播放器initMediaPlayer();} else {// 权限被拒绝,显示提示并关闭应用Toast.makeText(this, "拒绝权限将无法使用程序", Toast.LENGTH_SHORT).show();finish();}}}private void initMediaPlayer() {// 获取音乐文件的路径File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC), "music.map3");// 检查文件是否存在if (!file.exists()) {Toast.makeText(this, "文件不存在: " + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();return;}try {// 设置数据源并准备播放器mediaPlayer.setDataSource(file.getPath());mediaPlayer.prepare();} catch (IOException e) {throw new RuntimeException(e);}}@Overridepublic void onClick(View v) {if (v.getId() == R.id.btn_start) {if (!mediaPlayer.isPlaying()) {mediaPlayer.start(); // 开始}} else if (v.getId() == R.id.btn_pause) {if (mediaPlayer.isPlaying()) {mediaPlayer.pause(); // 暂停}} else if (v.getId() == R.id.btn_stop) {if (mediaPlayer.isPlaying()) {mediaPlayer.reset(); // 停止initMediaPlayer();}}}@Overrideprotected void onDestroy() {super.onDestroy();// 确保在销毁活动时释放媒体播放器资源if (mediaPlayer != null) {mediaPlayer.stop();mediaPlayer.release();}}
}

MediaPlayer

MediaPlayer 是 Android 提供的一个类,用于播放各种音频和视频文件。你可以用它来播放本地文件、网络流媒体或资源文件。下面是一些基本的用法:

  1. 创建 MediaPlayer 实例:

    MediaPlayer mediaPlayer = new MediaPlayer();
    
  2. 设置数据源: 你可以使用本地文件路径、资源 ID 或网络 URL 作为数据源。

    // 设置本地资源文件
    mediaPlayer.setDataSource(context, Uri.parse("file:///path/to/your/audio/file.mp3"));// 设置网络流媒体
    mediaPlayer.setDataSource("http://www.example.com/audiofile.mp3");// 设置资源 ID(例如 raw 文件夹中的文件)
    mediaPlayer = MediaPlayer.create(this, R.raw.music);
    
  3. 准备和开始播放:

    mediaPlayer = MediaPlayer.create(this, R.raw.music);
    // 如果使用的是本地文件或资源 ID
    
    mediaPlayer.prepareAsync(); // 如果使用的是网络流媒体
    mediaPlayer.start();
    
    1. 控制播放: 你可以暂停、继续或停止播放。
  mediaPlayer.pause();mediaPlayer.start();mediaPlayer.stop();
  1. 释放资源: 播放结束后或不再需要时,要释放资源。

    mediaPlayer.release();
    
  2. 设置监听器: 你可以设置播放完成、错误等事件的监听器。

    mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {// 播放完成}
    });mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {// 处理错误return false;}
    });
    

使用 MediaPlayer 的时候,确保在合适的生命周期阶段(如 onPauseonResume)管理其状态,避免资源泄漏。

五、播放视频

image-20240801121909033

VideoView 是 Android 提供的一个控件,用于在应用中播放视频。以下是 VideoView 常用的方法和属性的介绍:

方法

  1. setVideoPath(String path)
    • 设置视频的路径。可以是一个文件路径、URL 或资源路径。
    • 示例: videoView.setVideoPath("android.resource://" + getPackageName() + "/" + R.raw.video_file);
  2. setVideoURI(Uri uri)
    • 设置视频的 URI(统一资源标识符),这可以是文件 URI、内容 URI 或网络 URI。
    • 示例: videoView.setVideoURI(Uri.parse("http://www.example.com/video.mp4"));
  3. start()
    • 开始播放视频。如果视频已经在播放,调用此方法会重新开始播放视频。
    • 示例: videoView.start();
  4. pause()
    • 暂停视频播放。如果视频当前正在播放,调用此方法会暂停播放。
    • 示例: videoView.pause();
  5. stopPlayback()
    • 停止视频播放并释放资源。调用此方法后,视频将停止播放,并且需要重新设置视频路径或 URI。
    • 示例: videoView.stopPlayback();
  6. seekTo(int msec)
    • 将视频进度跳转到指定的时间位置,单位是毫秒。
    • 示例: videoView.seekTo(30000); // 跳转到 30 秒处
  7. getCurrentPosition()
    • 获取视频的当前播放位置,单位是毫秒。
    • 示例: int currentPosition = videoView.getCurrentPosition();
  8. getDuration()
    • 获取视频的总时长,单位是毫秒。
    • 示例: int duration = videoView.getDuration();
  9. isPlaying()
    • 检查视频是否正在播放。返回 true 如果视频正在播放,返回 false 如果视频处于暂停状态或未播放。
    • 示例: boolean isPlaying = videoView.isPlaying();

属性

  • setMediaController(MediaController controller)

    • 设置媒体控制器,用于提供播放、暂停、进度条等控制界面。可以使用默认的 MediaController 或自定义控制器。
    • 示例:
      MediaController mediaController = new MediaController(this);
      videoView.setMediaController(mediaController);
      mediaController.setAnchorView(videoView);
      
  • setKeepScreenOn(boolean keepScreenOn)

    • 设置是否保持屏幕常亮。可以用来防止视频播放时屏幕变暗。
    • 示例: `videoView.setKeepScreenOn(true);

示例

使用资源文件中的资源,不需要再申请权限

public class SecondActivity extends AppCompatActivity implements View.OnClickListener {// VideoView 用于播放视频private VideoView videoView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);videoView = findViewById(R.id.video_view);Button btn1 = findViewById(R.id.btn_start2);Button btn2 = findViewById(R.id.btn_pause2);Button btn3 = findViewById(R.id.btn_stop2);btn1.setOnClickListener(this);btn2.setOnClickListener(this);btn3.setOnClickListener(this);// 初始化视频路径initVideoPath();}// 设置视频的路径private void initVideoPath() {// 使用资源文件中的视频路径videoView.setVideoPath("android.resource://" + getPackageName() + "/" + R.raw.xbox);}@Overridepublic void onClick(View v) {// 根据点击的按钮 ID 执行相应的操作if (v.getId() == R.id.btn_start2) {// 播放视频if (!videoView.isPlaying())videoView.start();} else if (v.getId() == R.id.btn_pause2) {// 暂停视频播放if (videoView.isPlaying())videoView.pause();} else if (v.getId() == R.id.btn_stop2) {// 停止视频播放并重新设置视频路径if (videoView.isPlaying()) {videoView.stopPlayback();initVideoPath();}}}@Overrideprotected void onDestroy() {super.onDestroy();// 当活动销毁时,暂停视频播放if (videoView != null)videoView.suspend();}
}


感谢您的阅读
如有错误烦请指正


相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 收银系统源码-门店折扣活动应该怎么做
  • 你了解渗透测试吗?渗透测试在网络安全行业属于食物链什么层级?
  • vue-创建自己的CLI脚手架
  • 预测性维护:一种基于因果技术语言处理 (CTLP) 的智能故障诊断方法
  • js、ts、argular、nodejs学习心得
  • 研究人员可以采用什么策略来批判性地评估和综合其领域的不同文献
  • SSL组网的概念,SSL组网方式怎么实现
  • GuLi商城-商品服务-API-平台属性-新增分组与属性关联
  • 透明屏幕的显示原理与特点
  • 吴恩达机器学习-C1W3L2-逻辑回归之S型函数
  • 【c++】爬虫到底违不违法?
  • 美元/日元交易分析与市场展望
  • Django项目为后台admin用户添加密码
  • webstorm配置项目Typescript编译环境
  • Java 9 新特性(JKD9)
  • 10个确保微服务与容器安全的最佳实践
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • Hibernate最全面试题
  • HTTP中GET与POST的区别 99%的错误认识
  • JavaScript设计模式系列一:工厂模式
  • JAVA多线程机制解析-volatilesynchronized
  • Python进阶细节
  • 测试如何在敏捷团队中工作?
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 分布式任务队列Celery
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 力扣(LeetCode)21
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 原生 js 实现移动端 Touch 滑动反弹
  • 自定义函数
  • MPAndroidChart 教程:Y轴 YAxis
  • ​浅谈 Linux 中的 core dump 分析方法
  • ‌移动管家手机智能控制汽车系统
  • !$boo在php中什么意思,php前戏
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (26)4.7 字符函数和字符串函数
  • (C11) 泛型表达式
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (附源码)ssm高校实验室 毕业设计 800008
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (回溯) LeetCode 40. 组合总和II
  • (九)信息融合方式简介
  • (九十四)函数和二维数组
  • (七)Java对象在Hibernate持久化层的状态
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (转)linux 命令大全
  • (转)大型网站的系统架构
  • *上位机的定义
  • ./configure,make,make install的作用
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .Net Core和.Net Standard直观理解
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .net 无限分类