반응형
우리는 카메라를 사용하는 방벙은 두 가지가 있다.
◎ 카메라 앱
◎카메라 API
카메라 앱을 실행시킨다는 것은 내 앱에서 다른 앱을 실행 시킨다는 것이다. (새로운 Activity를 띄운다. 묵시적 Intent)
화면 구성: 버튼 1, 이미지 뷰1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<?xml version="1.0" encoding="utf-8"?>
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"
android:padding="16dp"
tools:context=".MainActivity">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="take a photo"
android:textAllCaps="false"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:onClick="clickphoto"
android:enabled="true"/>
</RelativeLayout>
|
이제 Activity.java 코드를 작성하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
package com.lcw.ex70cameratest;
import androidx.annotation.NonNull;
import android.Manifest;
import android.app.AlertDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
ImageView iv;
Button btn;
//캡쳐한 이미지를 저장할 파일의 경로 Uri
Uri imgUri=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv= findViewById(R.id.iv);
btn= findViewById(R.id.btn);
//카메라 앱에게 캡쳐한 사진을 저장하게
//하려면 외부 저장소의 읽고 쓰기 권한을
//부여해야함.
//마시멜로우부터 버전부터는 동적 퍼미션을 요구
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
int permissionResult=checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if(permissionResult== PackageManager.PERMISSION_DENIED){
//사용자에게 퍼미션을 요청하는 다이얼로그 보이기
String[] permissions= new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions,10);
}
}
}
//requestPermissions 메소드를 호출하여
//사용작가 퍼메션허용 여부를 선택하면
//자동으로 실행되는 콜백메소드
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case 10:
if(grantResults[0]==PackageManager.PERMISSION_GRANTED) //사용자가 허가 했다면
{
Toast.makeText(this, "카메라 기능 사용 가능", Toast.LENGTH_SHORT).show();
btn.setEnabled(true);
}else{//거부했다면
Toast.makeText(this, "카메라 기능 제한", Toast.LENGTH_SHORT).show();
btn.setEnabled(false);
}
break;
}
}
public void clickphoto(View view) {
//카메라 앱 실행을 위한 Intent 객체 생성
Intent intent= new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//캡쳐한 이미지를 저장할 파일의 경로(File객체 말고 Uri로)를
//Intent 에게 추가데이터(Extra)로 보내줘야함.
//imgUri에 경로를 설정하는 메소드
setImageUri(); //임의로 만든 메소드 (안에 내용이 너무 복잡해서 메소드로 만듬)
if(imgUri!=null) intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
//startActivityForResult(intent,100);
}
//imgUri 객체를 만들어주는 메소드
void setImageUri(){
//외부 저장소에 저장할 것을 권장함.
//이때 외부 저장소의 2가지 영역 중 하나를 선택
//1. 외부저장소의 앱 전용 영역 - 앱을 지우면 사진도 같이 지워짐
File path= getExternalFilesDir("photo"); // 외부메모리의 본인 패키지명으로된 폴더가 생기고 그 안에 files폴더 안에 photo라는 이름으로 폴더 경로를 지칭함
//2. 외부저장소의 공용영역 - 앱을 지워도 사진이 지워지지 않음.
path= Environment.getExternalStorageDirectory();//외부 메모리의 최상위 폴더 경로 [storage/emulated/0/ 인 경우가 많음]
//위에 path들은 예전꺼를 상기시키려고 쓴거임 사용안함
path= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
//경로를 결정했다면 저장할 파일명 .jpg 지정
//1) 날짜를 이용해서 파일명 지정
SimpleDateFormat sdf= new SimpleDateFormat("yyyyMMddhhmmss");
String fileName="IMG"+sdf.format(new Date())+".jpg";
File file= new File(path,fileName);
//2) 자동으로 임시파일명을 만들어주는 메소드 //1번 방벙을 더 많이 쓴다. 2번도 있다는 것만 알자.
try {
file=File.createTempFile("IMG_",".jpg",path);
} catch (IOException e) { e.printStackTrace();}
//일단 여기까지의 경로(file)가 잘 되었는지 확인
//new AlertDialog.Builder(this).setMessage(file.getAbsolutePath()).show();
//위 File 객체까지 잘되었다면...
//File객체를 콘텐츠의 경로를 지칭하는 Uri객체로 변경해야 카메라 앱이 인식함.
//File -> Uri
//Nougat(누가버전)부터 경로이미지 노출이 위험하다고 판단되어 File->Uri로 변환할때 FileProvider 가 필요함.
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N){
imgUri=Uri.fromFile(file);
}else{
//누가버전 이후부터 Uri.formFile()은 에러남
//다른 앱에게 파일의 접근을 허용해주도록 하는
//Provider를 이용해야함. 그 중에 FileProvider라는 것을 이용함.
}
//잘 되었는지 확인
new AlertDialog.Builder(this).setMessage(imgUri.getPath()).show();
}
}
|
위 코드에서 주의 할 점!! imgUri= FileProvider.getUriForFile(this, "com.lcw.ex70cameratest",file); 가 어떻게 들어가는지 순서가 있다.
<실행 화면> 아직 사진은 안찍었지만, 사진이 저장될 경로를 설정했다. [쉽지 않다.]
이제 카메라 앱을 열고, 찍은 사진을 이미지뷰에 보여주자.
이렇게 추가하면 사진을 찍고, 이미지 뷰에 보이고, 갤러리 앱에도 사진이 저장된걸 확인할 수 있다.
MainActiviy.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
package com.lcw.ex70cameratest;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.Manifest;
import android.app.AlertDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
ImageView iv;
Button btn;
//캡쳐한 이미지를 저장할 파일의 경로 Uri
Uri imgUri=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv= findViewById(R.id.iv);
btn= findViewById(R.id.btn);
//카메라 앱에게 캡쳐한 사진을 저장하게
//하려면 외부 저장소의 읽고 쓰기 권한을
//부여해야함.
//마시멜로우부터 버전부터는 동적 퍼미션을 요구
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
int permissionResult=checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if(permissionResult== PackageManager.PERMISSION_DENIED){
//사용자에게 퍼미션을 요청하는 다이얼로그 보이기
String[] permissions= new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions,10);
}
}
}
//requestPermissions 메소드를 호출하여
//사용작가 퍼메션허용 여부를 선택하면
//자동으로 실행되는 콜백메소드
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case 10:
if(grantResults[0]==PackageManager.PERMISSION_GRANTED) //사용자가 허가 했다면
{
Toast.makeText(this, "카메라 기능 사용 가능", Toast.LENGTH_SHORT).show();
btn.setEnabled(true);
}else{//거부했다면
Toast.makeText(this, "카메라 기능 제한", Toast.LENGTH_SHORT).show();
btn.setEnabled(false);
}
break;
}
}
public void clickphoto(View view) {
//카메라 앱 실행을 위한 Intent 객체 생성
Intent intent= new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//캡쳐한 이미지를 저장할 파일의 경로(File객체 말고 Uri로)를
//Intent 에게 추가데이터(Extra)로 보내줘야함.
//imgUri에 경로를 설정하는 메소드
setImageUri(); //임의로 만든 메소드 (안에 내용이 너무 복잡해서 메소드로 만듬)
if(imgUri!=null) intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
startActivityForResult(intent,100);
}
//startActivityForResult() 실행 후
//결과를 받을 때 자동 실행되는 메소드
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case 100:
if(resultCode==RESULT_OK){
Uri uri= data.getData();
if(uri!=null){
Glide.with(this).load(uri).into(iv);
}else{
//Bitmap으로 데이터 전달되었다면..
//우리가 지정한 imgUri의 경로에 사진이
//저장되어 있으니..
//Bitmap이미지 말고 imgUri의 사진을
//보여주도록..
//갤러리에 이미지(사진)가 보인다면 파일로 저장이 잘 된 것임.
//근데 갤러리앱에서 목록으로 나오지 않으면
//갤러리앱에게 새로 추가된 사진을
//스캔하도록... 방송하기!!
Intent intent= new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(imgUri);
sendBroadcast(intent);
}
}
break;
}
}
//imgUri 객체를 만들어주는 메소드
void setImageUri(){
//외부 저장소에 저장할 것을 권장함.
//이때 외부 저장소의 2가지 영역 중 하나를 선택
//1. 외부저장소의 앱 전용 영역 - 앱을 지우면 사진도 같이 지워짐
File path= getExternalFilesDir("photo"); // 외부메모리의 본인 패키지명으로된 폴더가 생기고 그 안에 files폴더 안에 photo라는 이름으로 폴더 경로를 지칭함
//2. 외부저장소의 공용영역 - 앱을 지워도 사진이 지워지지 않음.
path= Environment.getExternalStorageDirectory();//외부 메모리의 최상위 폴더 경로 [storage/emulated/0/ 인 경우가 많음]
//위에 path들은 예전꺼를 상기시키려고 쓴거임 사용안함
path= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
//경로를 결정했다면 저장할 파일명 .jpg 지정
//1) 날짜를 이용해서 파일명 지정
SimpleDateFormat sdf= new SimpleDateFormat("yyyyMMddhhmmss");
String fileName="IMG"+sdf.format(new Date())+".jpg";
File file= new File(path,fileName);
//2) 자동으로 임시파일명을 만들어주는 메소드 //1번 방벙을 더 많이 쓴다. 2번도 있다는 것만 알자.
try {
file=File.createTempFile("IMG_",".jpg",path);
} catch (IOException e) { e.printStackTrace();}
//일단 여기까지의 경로(file)가 잘 되었는지 확인
//new AlertDialog.Builder(this).setMessage(file.getAbsolutePath()).show();
//위 File 객체까지 잘되었다면...
//File객체를 콘텐츠의 경로를 지칭하는 Uri객체로 변경해야 카메라 앱이 인식함.
//File -> Uri
//Nougat(누가버전)부터 경로이미지 노출이 위험하다고 판단되어 File->Uri로 변환할때 FileProvider 가 필요함.
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N){
imgUri=Uri.fromFile(file);
}else{
//누가버전 이후부터 Uri.formFile()은 에러남
//다른 앱에게 파일의 접근을 허용해주도록 하는
//Provider를 이용해야함. 그 중에 FileProvider라는 것을 이용함.
}
//잘 되었는지 확인
//new AlertDialog.Builder(this).setMessage(imgUri.getPath()).show();
}
}
|
activity_main.xml 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<?xml version="1.0" encoding="utf-8"?>
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"
android:padding="16dp"
tools:context=".MainActivity">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="take a photo"
android:textAllCaps="false"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:onClick="clickphoto"
android:enabled="true"/>
</RelativeLayout>
|
AndroidManifest.xml 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
</intent-filter>
</activity>
<!-- 다른 앱에게 공개할 파일의 경로 지정 : 일종의 jdk 환경변수 같은 것 (어디서나 경로를 알아들을 수 있다.)-->
<!-- android:authorities : "유일한 식별자" (보통은 패키지명을 씀)-->
<provider
android:authorities="com.lcw.ex70cameratest"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<!-- 프로바이더가 공개할 파일의 경로들 지정 -->
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths"/>
</provider>
</application>
</manifest>
|
반응형
'안드로이드 웹앱 콘테츠 개발자 양성(국비지원) > Android 기능' 카테고리의 다른 글
Android Studio(기능) Location / Map [Camera -API] (0) | 2019.10.14 |
---|---|
Android Studio(기능) Location / Map [Camera -3 (동영상)] (0) | 2019.10.14 |
Android Studio(기능) Location / Map [Camera -1] (0) | 2019.10.14 |
Android Studio(기능) Location / Map [Google Map 사용 예제] (0) | 2019.10.11 |
Android Studio(기능) Location / Map 각 사이트 이용 방법 (0) | 2019.10.11 |
댓글