Android

[Android] 6주차 스터디 (Gallery)

poppy 2020. 11. 29. 18:36
반응형

이번에는 갤러리를 통해 사진을 가져와 이미지뷰에 보여주는 것을 해보겠습니다!

 

1. 권한을 추가해줍니다 - AndroidManifest.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

2. 이미지뷰를 만들어줍니다 - activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="300dp"
        android:layout_height="300dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:srcCompat="#123123" />

</androidx.constraintlayout.widget.ConstraintLayout>

일정한 크기로 가져오기 위해 width와 height를 지정해주었습니다. 

 

3. MainActivity.java를 작성해줍니다

먼저 권한설정을 위한 함수를 만들어줍니다

 public void checkSelfPermission() {
        String temp = ""; //권한에 대한 상수값

        //파일 읽기 권환 확인
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 
            temp += Manifest.permission.READ_EXTERNAL_STORAGE;
        }

        //파일 쓰기 권환 확인
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 
            temp += Manifest.permission.WRITE_EXTERNAL_STORAGE;
        }

        if(TextUtils.isEmpty(temp) == false){ //temp가 비어있지 않으면
            ActivityCompat.requestPermissions(this, temp.trim().split(" "), 1); 
        }
        else {
            //권한허용을 했는데 작동을 안할경우 추가해줌
        }
    }

temp는 권한에 대한 상수값을 저장해주는 변수입니다.

checkSelfPermission()으로 권한을 자가 진단합니다. 권한이 승인되어 있지 않으면 temp에 권한을 추가합니다.

PackageManager.PERMISSION_GRANTED은 상수값으로 권한이 승인되어있다는 의미입니다. 

Log를 통해 temp를 확인해보면 READ_EXTERNAL_STORAGE 와 WRITE_EXTERNAL_STORAGE 권한 문자열이 같이 들어가있습니다. 문자열이 붙어있기 때문에 split하여 분리해줘야 합니다. Log에서는 공백이 없어보이지만 두 문자열에 사이에 공백이 들어가있습니다

ActivityCompat.requestPermissions(this, temp.trim().split(" "), 1); - temp의 공백을 제거한 후 문자열을 분리하여 두 개의 권한을 추가해줍니다. 1은 requestCode입니다.

 

사용자가 시스템 권한 대화상자에 응답하면 시스템은 앱의 onRequestPermissionsResult() 구현을 호출합니다

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if(requestCode == 1) {
        int length = permissions.length;
        for(int i=0; i<length; i++) {
            if(grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                //허용 확인 되었을 때의 동작
            }
            else {

            }
        }
   }
}

아까 requestCode가 1이었으므로 requestCode == 1일 경우로 동작을 구현해줍니다. 이 코드에서는 딱히 동작을 정의해주지는 않았습니다.

 

변수를 정의해주고 onCreate()를 구현해줍니다.

ImageView iv;
private static final int GET_FROM_GALLERY = 101; //requestCode

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    checkSelfPermission();
    iv = (ImageView)findViewById(R.id.imageView);

    iv.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent i = new Intent();
            i.setType(MediaStore.Images.Media.CONTENT_TYPE); 
            i.setAction(Intent.ACTION_GET_CONTENT); 
            startActivityForResult(i, GET_FROM_GALLERY);
        }
    });
}

i.setType(MediaStore.Images.Media.CONTENT_TYPE); - 갤러리를 열어줍니다
i.setAction(Intent.ACTION_GET_CONTENT); - 갤러리에서 사진을 가져옵니다
startActivityForResult(i, GET_FROM_GALLERY); - 액티비티를 실행합니다. requestCode는 위에서 정의해준 상수값을 사용합니다. 숫자값으로 직접쓸 경우 외부에서 접근이 가능하므로 상수값으로 정의해서 접근하지 못하도록 해줍니다.

 

다음은 메인액티비티에서 갤러리로 넘어갔다가 다시 메인액티비티로 돌아올 때 호출되는 메소드입니다.

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if(requestCode == 101 && resultCode == RESULT_OK) { //startActivityForResult 정상 동작했다면
       try {
            InputStream is = getContentResolver().openInputStream(data.getData()); 
            Bitmap bm = BitmapFactory.decodeStream(is); 
            is.close();
            iv.setImageBitmap(bm);
        } catch (Exception e) { //예외처리
            e.printStackTrac();
        }
    }
    else if(requestCode == 101 && resultCode == RESULT_CANCELED) { //정상 동작하지않는다면
        Toast.makeText(this,"취소", Toast.LENGTH_LONG).show();
    }
}

InputStream is = getContentResolver().openInputStream(data.getData()); - contentResolver()는 내장데이터에 접근하기 위한 메소드입니다. InputStream을 통해 데이터를 가져옵니다. 
Bitmap bm = BitmapFactory.decodeStream(is); - is는 이미지파일이 아니라 데이터 타입이므로 비트맵으로 변환해줍니다.

iv.setImageBitmap(bm); - 갤러리에서 가져온 이미지를 이미지뷰에 넣어줍니다.

반응형