【Android】安卓多媒体之通知、摄像头、相册、播放音乐、视频用法总结
文章目录
- 一、通知
- 1. 申请权限
- 2. 创建通道
- 3. 创建通知
- 4. 发送通知
- 拓展功能
- 点击行为
- 更新通知
- 取消通知
- 锁屏通知
- 富文本通知
- 二、摄像头
- 1. 申请权限
- 2. 调用逻辑
- 3. 声明内容提供器
- 三、打开相册
- 1. 申请权限
- 检查并请求权限
- 处理权限请求结果
- 2.处理图片
- 从相册中选择图片
- 处理选择图片的结果
- 处理图片
- 获取图片真实路径
- 四、播放音乐
- 1.申请权限
- 2.处理音乐
- MediaPlayer
- 五、播放视频
- 方法
- 属性
- 示例
一、通知
在Android 8.0(API26)
后对通知更改了一些内容,以前是通过Notification,Builder(Context context).se..
来设置通知的震动、灯光、音效的设置,新内容加了NotificationChannel
(通知渠道),通过NotificatonChannel
来进行震动、灯光、音效的设置,且通知必须添加通知渠道,同样需进行版本判断,否则通知不会被发送。
步骤:
- 首先创建
NotificationManager
对象 - 创建
Notificationchannel
对象 - 通过
Notificationcompat.Builder(Context.Notification)
对象指定channel
并设置通知的各项信息,调用build()
方法创建Notifcation
对象 - 调用
NotificationManager
的notify(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
- 通道的用户可见的名称
- 通道的重要性
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. 创建通知
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()
方法发送消息,传递通知id
和Notification
对象
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()
,那么当用户单击通知时会从状态栏消失 - 通过
NotificationManager
的cancel(通知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())
- 使用
BigTextStyle
:BigTextStyle
用于显示大段文本内容,这些内容会在展开时显示完整。
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();
-
使用
BigPictureStyle
:BigPictureStyle
用于显示一张大图片,可以同时显示文本。 -
使用
InboxStyle
:InboxStyle
用于显示一组消息的列表,适合显示多个简短的消息。 -
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);}
二、摄像头
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;
}
四、播放音乐
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 提供的一个类,用于播放各种音频和视频文件。你可以用它来播放本地文件、网络流媒体或资源文件。下面是一些基本的用法:
-
创建
MediaPlayer
实例:MediaPlayer mediaPlayer = new MediaPlayer();
-
设置数据源: 你可以使用本地文件路径、资源 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);
-
准备和开始播放:
mediaPlayer = MediaPlayer.create(this, R.raw.music); // 如果使用的是本地文件或资源 ID
mediaPlayer.prepareAsync(); // 如果使用的是网络流媒体 mediaPlayer.start();
- 控制播放: 你可以暂停、继续或停止播放。
mediaPlayer.pause();mediaPlayer.start();mediaPlayer.stop();
-
释放资源: 播放结束后或不再需要时,要释放资源。
mediaPlayer.release();
-
设置监听器: 你可以设置播放完成、错误等事件的监听器。
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
的时候,确保在合适的生命周期阶段(如 onPause
和 onResume
)管理其状态,避免资源泄漏。
五、播放视频
VideoView
是 Android 提供的一个控件,用于在应用中播放视频。以下是 VideoView
常用的方法和属性的介绍:
方法
setVideoPath(String path)
- 设置视频的路径。可以是一个文件路径、URL 或资源路径。
- 示例:
videoView.setVideoPath("android.resource://" + getPackageName() + "/" + R.raw.video_file);
setVideoURI(Uri uri)
- 设置视频的 URI(统一资源标识符),这可以是文件 URI、内容 URI 或网络 URI。
- 示例:
videoView.setVideoURI(Uri.parse("http://www.example.com/video.mp4"));
start()
- 开始播放视频。如果视频已经在播放,调用此方法会重新开始播放视频。
- 示例:
videoView.start();
pause()
- 暂停视频播放。如果视频当前正在播放,调用此方法会暂停播放。
- 示例:
videoView.pause();
stopPlayback()
- 停止视频播放并释放资源。调用此方法后,视频将停止播放,并且需要重新设置视频路径或 URI。
- 示例:
videoView.stopPlayback();
seekTo(int msec)
- 将视频进度跳转到指定的时间位置,单位是毫秒。
- 示例:
videoView.seekTo(30000);
// 跳转到 30 秒处
getCurrentPosition()
- 获取视频的当前播放位置,单位是毫秒。
- 示例:
int currentPosition = videoView.getCurrentPosition();
getDuration()
- 获取视频的总时长,单位是毫秒。
- 示例:
int duration = videoView.getDuration();
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();}
}
感谢您的阅读
如有错误烦请指正