안드로이드 노트
[프로젝트1] 카메라, 갤러리 권한 및 firebase storage 사용한 방법
devRobin
2022. 3. 19. 10:27
1. AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2. arrays of permissions to be requested
String cameraPermissions[];
String storagePermission[];
//init arrays of permissions
cameraPermissions = new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE};
storagePermission = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
3. showImagePicDialog()
profileIv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
pd.setMessage("Updating Profile Picture");
profilePhoto = "image";
showImagePicDialog();
}
});
private void showImagePicDialog(){
//show dialog containing options camera and Gallery to pick the image
String options[]={"Camera","Gallery"};
AlertDialog.Builder builder = new AlertDialog.Builder(EditActivity.this);
builder.setTitle("Pick Image From");
builder.setItems(options,(dialog, i) -> {
//handle dialog item clicks
if(i == 0){
//Camera clicked
if(!checkCameraPermission()){
requestCameraPermission();
}
else{
pickFromCamera();
}
}
else if(i == 1){
//Gallery clicked
if(!checkStoragePermission()){
requestStoragePermission();
}
else {
pickFromGallery();
}
}
});
//create and show dialog
builder.create().show();
}
AlertDialog.Builder
참고: https://developer.android.com/guide/topics/ui/dialogs?hl=ko
4. Check if storage permission is enabled or not.
return true if enabled
return false if not enabled
private boolean checkStoragePermission(){
boolean result = ContextCompat.checkSelfPermission(EditActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE)==(PackageManager.PERMISSION_GRANTED);
return result;
}
private void requestStoragePermission(){
//request runtime storage permission
ActivityCompat.requestPermissions(EditActivity.this,storagePermission,STORAGE_REQUEST_CODE);
}
앱에 이미 권한이 부여되었는지 확인
사용자가 이미 앱에 특정 권한을 부여했는지 확인하려면 ContextCompat.checkSelfPermission() 메서드에 권한을 전달합니다. 이 메서드는 앱에 권한이 있는지에 따라 PERMISSION_GRANTED 또는 PERMISSION_DENIED를 반환합니다.
참고:https://developer.android.com/training/permissions/requesting?hl=ko
5. checkCameraPermission()
private boolean checkCameraPermission(){
//return true if enabled
//return false if not enabled
boolean result = ContextCompat.checkSelfPermission(EditActivity.this,Manifest.permission.CAMERA)==(PackageManager.PERMISSION_GRANTED);
boolean result1 = ContextCompat.checkSelfPermission(EditActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE)==(PackageManager.PERMISSION_GRANTED);
return result && result1;
}
private void requestCameraPermission(){
ActivityCompat.requestPermissions(EditActivity.this,cameraPermissions,CAMERA_REQUEST_CODE);
}
6.onRequestPermissionsResult
This method called when user press Allow or Deny from permission request dialog
Here we will handle permission cases (allowed & denied)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case CAMERA_REQUEST_CODE:{
//picking from camera, first check if camera and storage permissions allowed or not
if(grantResults.length>0){
boolean cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean writeStorageAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if(cameraAccepted && writeStorageAccepted){
//permissions enabled
pickFromCamera();
}
else {
//permissions denied
Toast.makeText(EditActivity.this,"Please enable camera & Storage permission",Toast.LENGTH_SHORT);
}
}
}
case STORAGE_REQUEST_CODE:{
//picking from gallery, first check if storage permissions allowed or not
if(grantResults.length>0){
boolean writeStorageAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if(writeStorageAccepted){
//permissions enabled
pickFromGallery();
}
else {
//permissions denied
Toast.makeText(EditActivity.this,"Please enable storage permission",Toast.LENGTH_SHORT);
}
}
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
권한 허가 요청 후 가져오기
7. pickFromCamera()
private void pickFromCamera(){
//Intent of picking image from device camera
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE,"Temp Pic");
values.put(MediaStore.Images.Media.DESCRIPTION,"Temp Description");
//put image uri
image_uri = this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,values);
//intent to start camera
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri);
startActivityForResult(cameraIntent, IMAGE_PICK_CAMERA_CODE);
}
ContentValues란?
이 클래스는 ContentResolver가 처리 할수 있는 값 집합을 저장하는데 사용됩니다.
ContentResolver는 콘텐트 프로바이더(ContentProvider)와 비즈니스 로직의 중계자 역할을 하고 있습니다.
ContentValues는 ContentResolver가 사용하는 데이터 운송 수단이라고 생각하시면 좋을 것 같습니다.
ContentValues 사용 순서
참고: https://choidev-1.tistory.com/57
startActivity vs. startActivityForResult
startActivity : 새 액티비티를 열어줌 (단방향)
startActivityForResult : 새 액티비티를 열어줌 + 결과값 전달 (쌍방향)
출처: https://jhshjs.tistory.com/49
8. pickFromGallery()
private void pickFromGallery(){
//pick from gallery
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
galleryIntent.setType("image/*");
startActivityForResult(galleryIntent,IMAGE_PICK_GALLERY_CODE);
}
9.onActivityResult
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
//This method will be called after picking image from camera or Gallery
if(resultCode == RESULT_OK){
if(requestCode == IMAGE_PICK_GALLERY_CODE){
//image is picked from gallery, get uri of image
image_uri = data.getData();
uploadProfilePhoto(image_uri);
}
if(requestCode == IMAGE_PICK_CAMERA_CODE){
//image is picked from camera, get uri of image
uploadProfilePhoto(image_uri);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
액티비티간 데이터 주고받기
출처: https://scshim.tistory.com/50
10. uploadProfilePhoto(Uri uri)
private void uploadProfilePhoto(Uri uri) {
//show progress
pd.show();
String filePathAndName = storagePath+""+profilePhoto+"_"+user.getUid();
StorageReference storageReference2nd = storageReference.child(filePathAndName);
storageReference2nd.putFile(uri)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//image is uploaded to storage, now get it's uri and store in user's database
Task<Uri> uriTask = taskSnapshot.getStorage().getDownloadUrl();
while(!uriTask.isSuccessful());
Uri downloadUri = uriTask.getResult();
//check if image is uploaded or not and uri is received
if(uriTask.isSuccessful()){
//image uploaded
//add/update uri in user's database
HashMap<String, Object> results = new HashMap<>();
results.put(profilePhoto, downloadUri.toString());
databaseReference.child(user.getUid()).updateChildren(results)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void unused) {
//uri in database of user is added successfully
//dismiss progress bar
pd.dismiss();
Toast.makeText(EditActivity.this,"Image Updated...",Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
//error adding url in database of user
//dismiss progress bar
pd.dismiss();
Toast.makeText(EditActivity.this,"Error Updating Image...",Toast.LENGTH_SHORT).show();
}
});
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
//there were some error(s), get and show error message, dismiss progress dialog
pd.dismiss();
Toast.makeText(EditActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}