多媒体是什么?
多媒体包括视频、音频等一系列娱乐功能。
通知
当应用程序不在前台运行,但又希望给用户发送信息时,就需要借助通知。发出通知后,手机状态栏会有通知图标,下拉状态栏可以查看具体的通知内容。
修改activity_main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/notice"
android:layout_height="wrap_content"
android:text="send notice"
android:layout_width="match_parent"/>
</LinearLayout>
为按钮添加点击事件:
- 创建PendingIntent为通知的点击事件,第一个参数为context,第二个参数为0,第三个参数为intent,第四个参数为0
- 通过getSystemService(NOTIFICATION_SERVICE)获取NotificationManager
- 通过Notification.Builder构建出Builder实例,设置相关属性
- 如果SDK大于26还需要创建NotificationChannel并设置setChannelId
- 通过builder.build()构建Notification实例
- 调用NotificationManager的notify()方法,传入唯一id和Notification实例
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button start = findViewById(R.id.start_service);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, otherActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, 0);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification.Builder builder = new Notification.Builder(MainActivity.this)
.setContentTitle("title")
.setContentText("text")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentIntent(pendingIntent)
.setAutoCancel(true);
if (Build.VERSION.SDK_INT > 26) {
NotificationChannel notificationChannel = new NotificationChannel("1", "test", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(notificationChannel);
builder.setChannelId("1");
}
Notification notification = builder.build();
notificationManager.notify(1,notification);
}
});
}
}
效果图:
另外,取消通知还可以通过,其中1为创建时的id:
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.cancel(1);
通知还可以加上音频提醒:
.setsound(Uri.fromFile(new File("/system/media/audio/ringtones/Luna.ogg")))
加上震动,接受长整型数组,偶数下标为静止时间,奇数下标为震动时间,震动需要申明权限VIBRATE:
.setVibrate(new long[]{0,1000,1000,1000})
加上LED呼吸灯,第一个参数为颜色,第二个参数为亮灯时长,第三个参数为暗灯时长:
.setLights(Color.GREEN,1000,1000)
如果需要显示长文字:
.setStyle(new NotificationCompat.BigTextStyle().bigText("xxxxxxxxxxxx"))
显示图片:
.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)))
设置优先级,有default、low、min、high、max可选:
.setPriority(NotificationCompat.PRIORITY_MAX)
调用摄像头
修改activity.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/take_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="take photo" />
<ImageView
android:id="@+id/picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</LinearLayout>
修改MainActivity:
- 创建File对象存储照片,通过getExternalCacheDir()方法放在sd卡应用关联缓存目录,具体为/sdcard/Android/data/<package name>/cache。如果放到其他位置需要进行运行时权限处理。
- sdk不大于24就调用Uri.fromFile转换成Uri对象,此时Uri标识真实路径
- 但sdk24之后就不允许使用真实路径Uri,调用FileProvider.getUriForFile()方法将File对象转换成封装过的Uri对象,第一个参数为context,第二个参数为任意唯一字符串,第三个参数为File对象
- 构建intent对象指定图片的输出地址
- 拍照完回调onActivityResult()方法,解析照片进行显示
public class MainActivity extends AppCompatActivity {
public static final int TAKE_PHOTO = 1;
private ImageView picture;
private Uri imageUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button takePhoto = findViewById(R.id.take_photo);
picture = findViewById(R.id.picture);
takePhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
File outputImage = new File(getExternalCacheDir(), "outputImage.jpg");
try {
if (outputImage.exists()) {
outputImage.delete();
}
outputImage.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT >= 24) {
imageUri = FileProvider.getUriForFile(MainActivity.this, "com.example.cameraalbumtest.fileprovider", outputImage);
} else {
imageUri = Uri.fromFile(outputImage);
}
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 {
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
picture.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
default:
break;
}
}
}
在Mainifest声明provider:
- name为固定
- authorities与FileProvider.getUriForFile()方法第二个参数一致
- <meta-data>指定Uri路径,并引用一个资源
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.cameraalbumtest.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
在res下创建xml文件夹并创建file_paths.xml:
- external-path指定Uri共享,
- name随便填
- path表示共享路径,空为整个sd卡共享
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="my_image"
path=""/>
</paths>
调用相册
修改activity.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/choose_from_album"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="choose from album" />
<ImageView
android:id="@+id/picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</LinearLayout>
修改MainActivity:
- 首先获取读写sd卡的运行时权限处理
- 构建Intent跳转到相册程序选择照片
- 回调onActivityResult根据sdk分别处理
- 因为sdk19以后就不能返回图片真实的Uri了,而是一个封装过的Uri
- 当大于sdk19时,还要分别判断Uri类型
- 当小于sdk19时,可直接从返回数据获取Uri
public class MainActivity extends AppCompatActivity {
public static final int CHOOSE_PHOTO = 2;
private ImageView picture;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
picture = findViewById(R.id.picture);
Button chooseFromAlbum = findViewById(R.id.choose_from_album);
chooseFromAlbum.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
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();
}
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] 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:
}
}
private void openAlbum() {
Intent intent = new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent, CHOOSE_PHOTO);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case CHOOSE_PHOTO:
if (resultCode == RESULT_OK) {
if (Build.VERSION.SDK_INT >= 19) {
handleImageOnKitkat(data);
} else {
handleImageBeforeKitkat(data);
}
}
break;
default:
break;
}
}
private void handleImageBeforeKitkat(Intent data) {
Uri uri = data.getData();
String ImagePath = getImagePath(uri, null);
displayImage(ImagePath);
}
@TargetApi(19)
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.valueOf(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);
}
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();
}
}
private String getImagePath(Uri externalContentUri, String selection) {
String path = null;
Cursor cursor = getContentResolver().query(externalContentUri, null, selection, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
}
}
播放音频
修改activity_main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/play"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="play" />
<Button
android:id="@+id/pause"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="pause" />
<Button
android:id="@+id/stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="stop" />
</LinearLayout>
添加权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
修改MainActivity,获取运行时权限,并设置点击事件:
public class MainActivity extends AppCompatActivity {
private MediaPlayer mediaPlayer =new MediaPlayer();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
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 {
initMediaPlayer();
}
Button play = findViewById(R.id.play);
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
});
Button pause = findViewById(R.id.pause);
pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}
});
Button stop = findViewById(R.id.stop);
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
}
private void initMediaPlayer() {
File file = new File(Environment.getExternalStorageDirectory(), "music.mp3");
try {
mediaPlayer.setDataSource(file.getPath());
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initMediaPlayer();
} else {
Toast.makeText(this, "you denied the permission", Toast.LENGTH_SHORT).show();
finish();
}
break;
default:
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
}
}
}
播放视频
修改activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/play"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="play" />
<Button
android:id="@+id/pause"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="pause" />
<Button
android:id="@+id/replay"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="replay" />
</LinearLayout>
<VideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
添加权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
修改MainActivity,获取运行时权限:
public class MainActivity extends AppCompatActivity {
private VideoView videoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
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 {
initVideo();
}
videoView = findViewById(R.id.video_view);
Button play = findViewById(R.id.play);
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!videoView.isPlaying()) {
videoView.start();
}
}
});
Button pause = findViewById(R.id.pause);
pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (videoView.isPlaying()) {
videoView.pause();
}
}
});
Button replay = findViewById(R.id.replay);
replay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (videoView.isPlaying()) {
videoView.resume();
}
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initVideo();
} else {
Toast.makeText(this, "you denied the permission", Toast.LENGTH_SHORT).show();
finish();
}
break;
default:
}
}
private void initVideo() {
File file = new File(Environment.getExternalStorageDirectory(), "movie.mp4");
videoView.setVideoPath(file.getPath());
}
@Override
protected void onDestroy() {
super.onDestroy();
if (videoView != null) {
videoView.suspend();
}
}
}