애플리케이션의 res/raw/ 디렉터리에 저장된 로컬 원시 리소스로 사용 가능한 오디오를 재생하는 방법
MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); // no need to call prepare(); create() does that for you
URI는 정보의 고유한 명칭으로 웹 주소를 나타내는 URL보다 더 상위의 개념
File 타입: file://파일패스/파일이름
file:///storage/emulated/0/Pictures/camera_image.jpg
안드로이드 리소스 타입: android.resource://패키지이름/리소스폴더/리소스이름
android.resource://com.example.kwanwoo.multimediatest/raw/instrumental
컨텐츠 타입: content://정보제공자/패스/아이디
content://media/external/video/media/154
Uri 클래스의 주요 메소드
static Uri parse(String uriString) - Uri문자열로부터 Uri 객체 생성
Uri image_Uri = Uri.parse("file:///storage/emulated/0/Pictures/camera_image.jpg");
static Uri.fromFile(File file) - file로부터 Uri 객체 생성
Uri image_Uri = Uri.fromFile(
new File(getExternalFilesDir(Environment.DIRECTORY_PICTURE).getPath()+
"/"+
"camera_image.jpg")));
사용방법
Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(getApplicationContext(), myUri);
// or just mediaPlayer.setDataSource(mFileName);
mMediaPlayer.prepare();
mediaPlayer.start();
인터넷 접근 권한(android.permission.INTERNET) 필요
AndroidMenifest.xml 파일에 다음 권한 추가
<manifest ... >
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
Android Platform API 28 이상의 디바이스에서는 ClearText 지원이 기본적으로 비활성화되어 있다.
이를 활성화 시키기위해서, AndroidMenifest.xml 파일의 application 태그에 다음 속성값을 설정
<application
android:usesCleartextTraffic="true"
... >
사용 방법 1 (UI 스레드에서 실행)
String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();
사용방법 2 (별도의 스레드에서 비동기 실행)
String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(url);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
mediaPlayer.prepareAsync();
MediaPlayer는 귀중한 시스템 리소스를 소비할 수 있습니다. 따라서 항상 특히 주의를 기울여 필요 이상으로 오래 MediaPlayer 인스턴스를 유지하지 않는지 확인해야 합니다.
액티비티의 onStop() 콜백 메소드에서 MediaPlayer 해제
protected void onStop() {
mediaPlayer.release();
mediaPlayer = null;
}
메소드 | 설명 |
---|---|
void pause() | 재생 일시 중지 |
boolean isPlaying() | 재생 중인지 검사 |
void seekTo(int msec) | msec 시간 위치로 재생 위치 이동 |
int getCurrentPosition() | 현재 재생 위치를 반환 |
예제
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
// ...
if (mMediaPlayer != null && mSelectedPosition == position) { // 이전 선택과 동일한 항목을 선택한 경우
if (mMediaPlayer.isPlaying()) { // 미디어가 재생 중인 경우
mPlaybackPosition = mMediaPlayer.getCurrentPosition();
mMediaPlayer.pause();
Toast.makeText(getApplicationContext(), "음악 파일 재생 중지됨.", Toast.LENGTH_SHORT).show();
} else { // 미디어가 재생 중이 아닌 경우
mMediaPlayer.seekTo(mPlaybackPosition);
mMediaPlayer.start();
Toast.makeText(getApplicationContext(), "음악 파일 재생 재시작됨.", Toast.LENGTH_SHORT).show();
}
} else { // 이전 선택과 다른 항목을 선택한 경우
// 미디어 재생
playAudioByUri(uri);
// 선택된 리스뷰 뷰 항목 위치 저장
mSelectedPosition = position;
}
MediaPlayer로도 비디오 재생이 가능하나, VideoView 위젯을 이용하면 매우 간단히 비디오 재생이 가능
VideoView 활용 절차
Java 코딩
[선택사항] 미디어콘트롤러 설정
재생할 동영상 URI 설정
재생 시작
필요한 권한
<manifest ... >
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>
오디오 녹음 절차
[주의] Android 6.0 이상부터는 앱 실행 중에 권한 검사 및 요청 필요
앱 시작시에 앱에서 필요한 권한 보유여부를 검사하고 없으면 요청한다.
requestRecordAudioPermission() 메소드는 RECORD_AUDIO권한을 요청한다.
protected void onCreate(Bundle savedInstanceState) {
//...
if (haveRecordAudioPermission())
initListView();
else
requestRecordAudioPermission();
}
private boolean haveRecordAudioPermission() {
return ContextCompat.checkSelfPermission(this,Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_GRANTED;
}
private void requestRecordAudioPermission() {
String[] permissions = {
Manifest.permission.RECORD_AUDIO
};
ActivityCompat.requestPermissions(
this,
permissions,
REQUEST_RECORD_AUDIO_FOR_MULTIMEDIA);
}
예제 코드
private void startAudioRec() {
* mMediaRecorder = new MediaRecorder();
* mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
* mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
* mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
// currentDateFormat(): 현재 시각을 “yyyyMMdd_HH_mm_ss” 형태로 반환
recFileN = "VOICE" + currentDateFormat() + ".mp4";
// 출력 파일의 위치를 앱 전용 외부저장소의 /Music/ 위치로 설정
* mMediaRecorder.setOutputFile(
* getExternalFilesDir(Environment.DIRECTORY_MUSIC).getPath()+"/" + recFileN);
try {
* mMediaRecorder.prepare();
Toast.makeText(getApplicationContext(), "녹음을 시작하세요.", Toast.LENGTH_SHORT).show();
* mMediaRecorder.start();
} catch (Exception ex) {
Log.e("SampleAudioRecorder", "Exception : ", ex);
}
}
private void stopAudioRec() {
* mMediaRecorder.stop();
* mMediaRecorder.release();
mMediaRecorder = null;
Uri uri = Uri.parse("file://" +
getExternalFilesDir(Environment.DIRECTORY_MUSIC).getPath()+
"/" +
recFileN);
// 리스트 뷰의 항목으로 녹음된 파일 이름과 URI를 추가
mAdapter.addItem(new MediaItem(MediaItem.SDCARD, recFileN,uri));
Toast.makeText(getApplicationContext(), "녹음이 중지되었습니다.", Toast.LENGTH_SHORT).show();
}
특별한 Permission이 필요 없음
카메라 앱 요청
private void dispatchTakePictureIntent() {
* Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// resolveActivity(): takePictureIntent를 처리할 수 있는 (사진찍기) 액티비티 반환
startActivity(takePictureIntent);
}
}
Uri 객체를 Extras를 통해 카메라 앱으로 전달
[주의] Android 7.0 이상부터는 FileProvider의 getUriForFile(Context, String, File)를 통해 해당 파일 객체의 content://URI를 획득
[사전조건] 외부 저장소에 저장하기 위해서 Permission 획득 과정 필요
*Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
If (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// 1. 카메라 앱으로 찍은 이미지를 저장할 파일 객체 생성
mPhotoFileName = "IMG"+currentDateFormat()+".jpg";
mPhotoFile = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),
mPhotoFileName);
if (mPhotoFile !=null) {
// 2. 생성된 파일 객체에 대한 Uri 객체를 얻기
Uri imageUri = FileProvider.getUriForFile(this,
"com.example.kwanwoo.multimediatest", mPhotoFile);
// 3. Uri 객체를 Extras를 통해 카메라 앱으로 전달
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
* startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
} else
Toast.makeText(getApplicationContext(), "file null", Toast.LENGTH_SHORT).show();
}
onActivityResult() 메소드에서 저장된 사진을 이미지 뷰에 출력
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
if (mPhotoFileName != null) {
mPhotoFile = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),
mPhotoFileName);
ImageView imageView = findViewById(R.id.imageView);
imageView.setImageURI(Uri.fromFile(mPhotoFile)); }
}
}
카메라 앱으로 전달
static final int REQUEST_VIDEO_CAPTURE = 2;
private void dispatchTakeVideoIntent() {
// 1. 동영상 캡처 작업 요청을 포함한 인텐트를 생성
* Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
//2. 카메라 앱으로 찍은 동영상을 저장할 파일 객체 생성
mVideoFileName = "VIDEO"+currentDateFormat()+".mp4";
File destination = new File(getExternalFilesDir(Environment.DIRECTORY_MOVIES),
mVideoFileName);
if (destination != null) {
//3. 생성된 파일 객체에 대한 Uri 객체를 얻기
Uri videoUri = FileProvider.getUriForFile(this,
"com.example.kwanwoo.multimediatest", destination);
//4. Uri 객체를 Extras를 통해 카메라 앱으로 전달
takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri);
startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE);
}
}
onActivityResult() 메소드에서 결과 코드가 RESULT_OK인 경우에, 촬영 결과를 저장한 파일 이름을 리스뷰의 항목으로 추가
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
...생략...
if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) {
if (mVideoFileName != null) {
mAdapter.addItem(new MediaItem(
MediaItem.SDCARD,
mVideoFileName,
MediaItem.VIDEO));
} else
Toast.makeText(getApplicationContext(), "!!! null video.", Toast.LENGTH_LONG).show();
}
}
특별한 Permission이 필요 없음
Photo/Gallery 앱 요청
private void dispatchPickPictureIntent() {
Intent pickPictureIntent = new Intent(Intent.ACTION_PICK);
pickPictureIntent.setType("image/*");
if (pickPictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(pickPictureIntent,REQUEST_IMAGE_PICK);
}
}
onActivityResult() 메소드에서 선택된 사진 결과를 이미지 뷰에 출력하기
선택된 사진 결과는 콘텐츠 Uri 형식으로 인텐트 객체를 통해 전달됨
Example
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_PICK && resultCode == RESULT_OK) {
Uri imgUri = data.getData();
ImageView imageView = findViewById(R.id.imageView);
imageView.setImageURI(imgUri);
}
콘텐츠 Uri 형식의 사진 결과를 외부 저장소 파일로 저장하기
MediaStore.Images.Media 클래스의 getBitmap()를 통해 Uri로부터 비트맵 얻기
Bitmap getBitmap (ContentResolver cr, Uri url)
Bitmap 클래스의 compress 메소드를 이용하면 비트맵을 다양한 형식으로 저장할 수 있다.
compress(Bitmap.CompressFormat format, int quality, OutputStream stream)
Example
private void saveToExternalFile(Uri imgUri) {
try {
Bitmap imgBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imgUri);
mPhotoFileName = "IMG"+currentDateFormat()+".jpg";
mPhotoFile = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), mPhotoFileName);
imgBitmap.compress(Bitmap.CompressFormat.JPEG,100,
new FileOutputStream(mPhotoFile));
} catch (IOException e) {}
}