本demo的功能是将assets文件夹中的图片、音频、视频保存至sd card中,对android 10 以上和以下均作了处理。
1、基础配置
权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
layout
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- 图片 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/id_btn_save_image"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:background="@color/black"
android:gravity="center_horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="save image"
android:textColor="@color/white"
android:textSize="30dp" />
<TextView
android:id="@+id/id_btn_show_image"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:background="@color/black"
android:gravity="center_horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="show image"
android:textColor="@color/white"
android:textSize="30dp" />
</LinearLayout>
<ImageView
android:id="@+id/id_image"
android:layout_width="180dp"
android:layout_height="140dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:background="@color/gray" />
<View
android:layout_width="match_parent"
android:layout_marginTop="10dp"
android:layout_height="2dp"
android:background="@color/gray"/>
<!-- 音频 -->
<TextView
android:id="@+id/id_btn_save_music"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="20dp"
android:layout_marginRight="10dp"
android:background="@color/black"
android:gravity="center_horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="save music"
android:textColor="@color/white"
android:textSize="30dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/id_btn_play_music"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:background="@color/black"
android:gravity="center_horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="play music"
android:textColor="@color/white"
android:textSize="30dp" />
<TextView
android:id="@+id/id_btn_pause_music"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:background="@color/black"
android:gravity="center_horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="pause music"
android:textColor="@color/white"
android:textSize="30dp" />
<TextView
android:id="@+id/id_btn_stop_music"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:background="@color/black"
android:gravity="center_horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="stop music"
android:textColor="@color/white"
android:textSize="30dp" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_marginTop="10dp"
android:layout_height="2dp"
android:background="@color/gray"/>
<!-- 视频 -->
<TextView
android:id="@+id/id_btn_save_video"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="20dp"
android:layout_marginRight="10dp"
android:background="@color/black"
android:gravity="center_horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="save video"
android:textColor="@color/white"
android:textSize="30dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/id_btn_play_video"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:background="@color/black"
android:gravity="center_horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="play video"
android:textColor="@color/white"
android:textSize="30dp" />
<TextView
android:id="@+id/id_btn_pause_video"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:background="@color/black"
android:gravity="center_horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="pause video"
android:textColor="@color/white"
android:textSize="30dp" />
<TextView
android:id="@+id/id_btn_stop_video"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:background="@color/black"
android:gravity="center_horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="stop video"
android:textColor="@color/white"
android:textSize="30dp" />
</LinearLayout>
<VideoView
android:id="@+id/id_video_view"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_width="match_parent"
android:layout_height="50dp" />
</LinearLayout>
</ScrollView>
BaseActivity
abstract public class BaseActivity extends AppCompatActivity {
@BindView(R.id.id_image)
ImageView imageView;
@BindView(R.id.id_btn_save_image)
protected TextView btnSaveImage;
@BindView(R.id.id_btn_show_image)
protected TextView btnShowImage;
@BindView(R.id.id_btn_save_music)
protected TextView btnSaveMusic;
@BindView(R.id.id_btn_play_music)
protected TextView btnPlayMusic;
@BindView(R.id.id_btn_pause_music)
protected TextView btnPauseMusic;
@BindView(R.id.id_btn_stop_music)
protected TextView btnStopMusic;
@BindView(R.id.id_video_view)
VideoView videoView;
@BindView(R.id.id_btn_save_video)
protected TextView btnSaveVideo;
@BindView(R.id.id_btn_play_video)
protected TextView btnPlayVideo;
@BindView(R.id.id_btn_pause_video)
protected TextView btnPauseVideo;
@BindView(R.id.id_btn_stop_video)
protected TextView btnStopVideo;
private Unbinder unbinder = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_base);
unbinder = ButterKnife.bind(this);
initView();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (unbinder != null) {
unbinder.unbind();
}
}
/**
* 初始化界面
*/
abstract protected void initView();
/**
* 获取 Activity
*
* @return
*/
protected BaseActivity getActivity() {
return this;
}
/**
* 提示信息
*
* @param tips
*/
protected void disPlayTips(String tips) {
Toast.makeText(getActivity(), tips, Toast.LENGTH_SHORT).show();
}
}
2、代码示例
Activity
public class SdCardActivity extends BaseActivity {
public static final String TAG = "SdCardActivity";
public static final int PERMISSION_REQUEST_CODE = 1;
private SdCardManager imageSdCardManager = null;
private SdCardManager musicSdCardManager = null;
private SdCardManager videoSdCardManager = null;
private MediaPlayer musicMediaPlayer = null;
@Override
protected void initView() {
imageSdCardManager = new SdCardManager(getActivity(), "test_image.png", SdCardManager.TYPE_IMAGE);
musicSdCardManager = new SdCardManager(getActivity(), "test_music.mp3", SdCardManager.TYPE_AUDIO);
videoSdCardManager = new SdCardManager(getActivity(), "test_video.mp4", SdCardManager.TYPE_VIDEO);
//权限申请
ActivityCompat.requestPermissions(this, new String[]{READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
//保存图片
btnSaveImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
imageSdCardManager.saveMediaToSdCard();
if (imageSdCardManager.getMediaUriFromSdCard() != null) {
disPlayTips("图片保存成功");
}
}
});
//展示图片
btnShowImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
Uri imageUri = imageSdCardManager.getMediaUriFromSdCard();
ParcelFileDescriptor parcelFileDescriptor = getContentResolver().openFileDescriptor(imageUri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
imageView.setImageBitmap(bitmap);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "------ show picture Exception : " + e.getMessage());
}
}
});
//保存音乐
btnSaveMusic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
musicSdCardManager.saveMediaToSdCard();
Uri musicUri = musicSdCardManager.getMediaUriFromSdCard();
if (musicUri != null) {
musicMediaPlayer = MediaPlayer.create(getActivity(), musicUri);
disPlayTips("音乐保存成功");
}
}
});
//播放音乐
btnPlayMusic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (musicMediaPlayer != null) {
musicMediaPlayer.start();
}
}
});
//暂停音乐
btnPauseMusic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (musicMediaPlayer != null) {
musicMediaPlayer.pause();
}
}
});
//停止音乐
btnStopMusic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (musicMediaPlayer != null) {
musicMediaPlayer.stop();
}
}
});
//保存视频
btnSaveVideo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
videoSdCardManager.saveMediaToSdCard();
Uri videoUri = videoSdCardManager.getMediaUriFromSdCard();
if (videoUri != null) {
disPlayTips("视频保存成功");
videoView.setVideoURI(videoUri);
}
}
});
//播放视频
btnPlayVideo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (videoSdCardManager.getMediaUriFromSdCard() != null) {
videoView.start();
}
}
});
//暂停视频
btnPauseVideo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (videoSdCardManager.getMediaUriFromSdCard() != null) {
videoView.pause();
}
}
});
//停止视频
btnStopVideo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (videoSdCardManager.getMediaUriFromSdCard() != null) {
videoView.stopPlayback();
}
}
});
}
}
SdCardManager
public class SdCardManager {
public static final String TAG = "SdCardManager";
/**
* BUFFER_SIZE 缓存区大小
*/
public static final int BUFFER_SIZE = 4096;
/**
* TYPE_IMAGE 图片
* TYPE_AUDIO 音频
* TYPE_VIDEO 视频
*/
public static final String TYPE_IMAGE = "image/jpeg";
public static final String TYPE_AUDIO = "audio/mpeg";
public static final String TYPE_VIDEO = "video/mp4";
/**
* mediaUri Android 10 及以上 多媒体文件 uri
*/
private Uri mediaUri = null;
/**
* Android 10 以下 多媒体文件保存路径
* <p>
* SAVE_PATH_IMAGE 图片路径
* SAVE_PATH_AUDIO 音频路径
* SAVE_PATH_VIDEO 视频路径
*/
public static final String SAVE_PATH_IMAGE = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Image";
public static final String SAVE_PATH_AUDIO = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Music";
public static final String SAVE_PATH_VIDEO = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Video";
/**
* 需要的参数
*/
private Context context = null;
private String fileName = null;
private String miniType = null;
/**
* 构造函数
*
* @param context
* @param fileName
* @param miniType
*/
public SdCardManager(Context context, String fileName, String miniType) {
this.context = context;
this.fileName = fileName;
this.miniType = miniType;
}
/**
* 获取 assets 中的文件
*
* @return
* @throws IOException
*/
private InputStream getInputStreamFromAssets() throws IOException {
return context.getResources().getAssets().open(fileName);
}
/**
* 根据 miniType 获取 ContentValues
*
* @return
*/
private ContentValues getContentValuesByMiniType() {
if (miniType.equals(TYPE_IMAGE)) {
//图片
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
contentValues.put(MediaStore.Images.Media.MIME_TYPE, miniType);
contentValues.put(MediaStore.Images.Media.DESCRIPTION, "This is a picture");
contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
return contentValues;
} else if (miniType.equals(TYPE_AUDIO)) {
//音频
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Audio.Media.DISPLAY_NAME, fileName);
contentValues.put(MediaStore.Audio.Media.MIME_TYPE, miniType);
contentValues.put(MediaStore.Audio.Media.RELATIVE_PATH, Environment.DIRECTORY_MUSIC);
return contentValues;
} else if (miniType.equals(TYPE_VIDEO)) {
//视频
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Video.Media.DISPLAY_NAME, fileName);
contentValues.put(MediaStore.Video.Media.MIME_TYPE, miniType);
contentValues.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_MOVIES);
return contentValues;
} else {
return null;
}
}
/**
* 通过 miniType 获取媒体库的 uri
*
* @return
*/
private Uri getUriByMiniType() {
if (miniType.equals(TYPE_IMAGE)) {
//图片
return MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if (miniType.equals(TYPE_AUDIO)) {
//音频
return MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
} else if (miniType.equals(TYPE_VIDEO)) {
//视频
return MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}
return null;
}
/**
* 根据 uri 删除旧的文件
*/
private void deleteFileByMiniType() {
if (miniType.equals(TYPE_IMAGE)) {
//图片
context.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media.DISPLAY_NAME + "=?", new String[]{fileName});
} else if (miniType.equals(TYPE_AUDIO)) {
//音频
context.getContentResolver().delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MediaStore.Audio.Media.DISPLAY_NAME + "=?", new String[]{fileName});
} else if (miniType.equals(TYPE_VIDEO)) {
//视频
context.getContentResolver().delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, MediaStore.Video.Media.DISPLAY_NAME + "=?", new String[]{fileName});
}
}
/**
* 保存多媒体文件到 sdCard
*
* @return
*/
public void saveMediaToSdCard() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//Android 10 及以上
ContentValues contentValues = getContentValuesByMiniType();
ContentResolver contentResolver = context.getContentResolver();
deleteFileByMiniType();
mediaUri = contentResolver.insert(getUriByMiniType(), contentValues);
if (mediaUri != null) {
ParcelFileDescriptor parcelFileDescriptor = contentResolver.openFileDescriptor(mediaUri, "w");
FileOutputStream fileOutputStream = new FileOutputStream(parcelFileDescriptor.getFileDescriptor());
InputStream inputStream = getInputStreamFromAssets();
byte[] buffer = new byte[BUFFER_SIZE];
while (true) {
int numRead = inputStream.read(buffer);
if (numRead == -1) {
break;
}
fileOutputStream.write(buffer, 0, numRead);
}
fileOutputStream.flush();
fileOutputStream.close();
parcelFileDescriptor.close();
}
} else {
//Android 10 以下
String savePath = getSavePathByMiniType();
File dir = new File(savePath);
if (!dir.exists()) {
dir.mkdir();
}
File file = new File(dir, fileName);
FileOutputStream fileOutputStream = new FileOutputStream(file);
InputStream inputStream = getInputStreamFromAssets();
byte[] buffer = new byte[BUFFER_SIZE];
while (true) {
int numRead = inputStream.read(buffer);
if (numRead == -1) {
break;
}
fileOutputStream.write(buffer, 0, numRead);
}
fileOutputStream.flush();
//保存后发送广播通知更新数据库
Uri uri = Uri.fromFile(file);
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
fileOutputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "------ save Exception : " + e.getMessage());
}
}
/**
* Android10以下,获取文件保存路径
*
* @return
*/
private String getSavePathByMiniType() {
String savePath = "";
if (miniType.equals(TYPE_IMAGE)) {
//图片
savePath = SAVE_PATH_IMAGE;
} else if (miniType.equals(TYPE_AUDIO)) {
//音频
savePath = SAVE_PATH_AUDIO;
} else if (miniType.equals(TYPE_VIDEO)) {
//视频
savePath = SAVE_PATH_VIDEO;
}
return savePath;
}
/**
* 获取 sd card 中媒体文件的 uri
*
* @return
*/
public Uri getMediaUriFromSdCard() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//Android 10 及以上
return mediaUri;
} else {
//Android 10 以下
File dir = new File(getSavePathByMiniType());
File file = new File(dir, fileName);
return Uri.fromFile(file);
}
}
}