애플리케이션의 res/raw/ 디렉터리에 저장된 로컬 원시 리소스로 사용 가능한 오디오를 재생하는 방법
    MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
    mediaPlayer.start(); // no need to call prepare(); create() does that for youURI는 정보의 고유한 명칭으로 웹 주소를 나타내는 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/154Uri 클래스의 주요 메소드
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) {}
    }