MainActivity

...더보기
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
186
187
188
189
190
package com.example.boostcoursepractice;
 
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
 
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
 
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
 
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
 
import java.io.File;
import java.net.URL;
import java.util.HashMap;
 
public class MainActivity extends AppCompatActivity {
 
    MediaRecorder recorder;
    String filename;
 
    MediaPlayer player;
    int position = 0;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        File sdcard = Environment.getExternalStorageDirectory();
        File file = new File(sdcard, "recorded.mp4");
        filename = file.getAbsolutePath();
        Log.d("MainActivity""저장할 파일명 : " + filename);
 
        Button button = (Button) findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                palyAudio();
            }
        });
 
 
        Button button2 = (Button) findViewById(R.id.button2);
 
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                pauseAudio();
            }
        });
 
        Button button3 = (Button) findViewById(R.id.button3);
 
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                resumeAudio();
            }
        });
 
        Button button4 = (Button) findViewById(R.id.button4);
 
        button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                stopAudio();
            }
        });
 
        Button button5 = (Button) findViewById(R.id.button5);
 
        button5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                recordAudio();
            }
        });
 
        Button button6 = (Button) findViewById(R.id.button6);
 
        button6.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                stopRecording();
            }
        });
    }
 
    public void palyAudio() {
        try {
            closePlayer();
 
            player = new MediaPlayer();
            player.setDataSource(filename);
            player.prepare();
            player.start();
 
            Toast.makeText(this"재생 시작됨", Toast.LENGTH_LONG).show();
 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public void pauseAudio() {
        if (player != null && player.isPlaying()) {
            position = player.getCurrentPosition();
            player.pause();
 
            Toast.makeText(this"일시 정지지됨", Toast.LENGTH_LONG).show();
        }
    }
 
    public void resumeAudio() {
        if (player != null && !player.isPlaying()) {
            player.seekTo(position);
            player.start();
 
            Toast.makeText(this"재시작됨", Toast.LENGTH_LONG).show();
        }
    }
 
    public void stopAudio() {
        if (player != null && player.isPlaying()) {
            player.stop();
 
            Toast.makeText(this"중지됨", Toast.LENGTH_LONG).show();
        }
    }
 
    public void closePlayer() {
        if (player != null) {
            player.release();
            player = null;
        }
    }
 
    public void recordAudio() {
        recorder = new MediaRecorder();
 
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
 
        recorder.setOutputFile(filename);
 
        try {
            recorder.prepare();
            recorder.start();
 
            Toast.makeText(this"녹음 시작됨", Toast.LENGTH_LONG).show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public void stopRecording(){
        if(recorder != null){
            recorder.stop();
            recorder.release();
            recorder = null ;
 
            Toast.makeText(this"녹음 중지됨", Toast.LENGTH_LONG).show();
        }
    }
}
 
cs

 

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical">
 
    <Button
        android:id="@+id/button5"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="녹음시작" />
 
    <Button
        android:id="@+id/button6"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="녹음중지" />
 
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="재생" />
 
    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="일시정지" />
 
    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="재시작" />
 
    <Button
        android:id="@+id/button4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="정지" />
</LinearLayout>
cs

 

기존에 진행 했던 '7-2-1 음악 재생하기'에서 좀 더 확장하여 구현하였다.  항상 종료가 될 때는 아래처럼

 

recorder.stop();

            recorder.release();

            recorder = null ;

 

자원을 해제하는 것을 잊지 말자

 

결과화면

 

MainActivity

...더보기
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
package com.example.boostcoursepractice;
 
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
 
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
 
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
 
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
 
import java.io.File;
import java.net.URL;
import java.util.HashMap;
 
public class MainActivity extends AppCompatActivity {
 
    VideoView videoView;
 
    public static String url = "http://sites.google.com/site/ubiaccessmobile/sample_video.mp4";
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        videoView = (VideoView) findViewById(R.id.videoView);
 
        MediaController mediaController = new MediaController(this);
        videoView.setMediaController(mediaController);
        videoView.setVideoURI(Uri.parse(url));
        videoView.requestFocus();
 
        videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mediaPlayer) {
                Toast.makeText(getApplicationContext(), "동영상 준비됨.", Toast.LENGTH_LONG).show();
            }
        });
 
        Button button = (Button) findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                videoView.seekTo(0);
                videoView.start();
            }
        });
 
    }
}
cs

 

activity_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical">
 
 
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="시작" />
 
    <VideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>
 
cs

 

동영상 재생은 일단 위 코드처럼 하면 된다. 이때 부연설명을 하자면 아래의 코드처럼

 

 videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

            @Override

            public void onPrepared(MediaPlayer mediaPlayer) {

                Toast.makeText(getApplicationContext(), "동영상 준비됨.", Toast.LENGTH_LONG).show();

            }

        });

 

비디오뷰에 setOnPreparedListener로 onPrepared메서드를 오버라이드한 OnPreparedListener를 설정한다면 requestFocus로 시작하여 비디오 재생 준비가 끝나면 onPrepared메서드가 호출되어 준비종료가 됬다는 것을 알수 있다. 그 이후로 동영상을 재생시켜주면 된다.

 

 

결과화면

 

MainActivity

...더보기
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
package com.example.boostcoursepractice;
 
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
 
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
 
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
 
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
 
import java.io.File;
import java.net.URL;
import java.util.HashMap;
 
public class MainActivity extends AppCompatActivity {
 
    public static String url = "http://sites.google.com/site/ubiaccessmobile/sample_audio.amr";
 
    MediaPlayer player;
    int position = 0;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Button button = (Button) findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                palyAudio();
            }
        });
 
 
        Button button2 = (Button) findViewById(R.id.button2);
 
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                pauseAudio();
            }
        });
 
        Button button3 = (Button) findViewById(R.id.button3);
 
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                resumeAudio();
            }
        });
 
        Button button4 = (Button) findViewById(R.id.button4);
 
        button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                stopAudio();
            }
        });
 
 
    }
 
    public void palyAudio() {
        try {
            closePlayer();
 
            player = new MediaPlayer();
            player.setDataSource(url);
            player.prepare();
            player.start();
 
            Toast.makeText(this"재생 시작됨", Toast.LENGTH_LONG).show();
 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public void pauseAudio()
    {
        if(player != null && player.isPlaying()){
            position = player.getCurrentPosition();
            player.pause();
 
            Toast.makeText(this"일시 정지지됨",Toast.LENGTH_LONG).show();
        }
    }
 
    public void resumeAudio()
    {
        if(player != null && !player.isPlaying()){
            player.seekTo(position);
            player.start();
 
            Toast.makeText(this"재시작됨",Toast.LENGTH_LONG).show();
        }
    }
 
    public void stopAudio()
    {
        if(player != null && player.isPlaying()){
            player.stop();
 
            Toast.makeText(this"중지됨",Toast.LENGTH_LONG).show();
        }
    }
 
        public void closePlayer(){
            if(player != null){
                player.release();
                player = null ;
            }
    }
}
cs

 

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
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical">
 
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="재생" />
 
    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="일시정지" />
 
    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="재시작" />
 
    <Button
        android:id="@+id/button4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="정지" />
</LinearLayout>
 
cs

 

음악을 재생하기 위해서는 MediaPlayer를 이용하면 된다. 

 

구현은 위 코드대로 하면 되고 중요한 것은 스피커는 하나의 자원이기 때문에 항상 다 쓰고 나면 아래처럼

 

 if(player != null){

                player.release();

                player = null ;

            }

 

해제를 해줘야 한다.

 

 

결과화면

 

 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

방법1(카메라 앱을 이용)

 

MainActivity

...더보기
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
package com.example.boostcoursepractice;
 
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
 
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
 
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
 
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
 
import java.io.File;
import java.net.URL;
import java.util.HashMap;
 
public class MainActivity extends AppCompatActivity {
 
    ImageView imageView ;
 
    File file ;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        File sdcard = Environment.getExternalStorageDirectory() ;
        file = new File(sdcard, "capture.jpg");
 
        imageView = (ImageView) findViewById(R.id.imageView);
 
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                capture();
            }
        });
    }
 
    public void capture()
    {
 
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
 
        startActivityForResult(intent, 101);
    }
 
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
 
        if(requestCode == 101 && resultCode == Activity.RESULT_OK) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = 8 ;
            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
            imageView.setImageBitmap(bitmap);
        }
    }
}
cs

 

activity_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical">
 
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="사진찍기" />
 
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:srcCompat="@android:drawable/sym_def_app_icon" />
</LinearLayout>
 
cs

 

카메라는 이용하는 방법으로는 첫번째로는 카메라 앱을 이용하여 하는 방식이 있다. 아래의 코드 처럼

 

        File sdcard = Environment.getExternalStorageDirectory() ;

        file = new File(sdcard, "capture.jpg");

 

우선 sd카드에 file을 열어주고 없으면 생성된다. 여기서는 capture.jpg라고 파일을 열어주거나 생성되게 함 그리고 나서는

 

 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));

 

        startActivityForResult(intent, 101);

 

위처럼 인텐트를 통하여 카메라 앱을 열어주고 사진을 찍으면 아까 생성한 capture.jpg에 저장되도록 인자로 그 uri를 넘겨준다. 마지막으로

 

   protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {

        super.onActivityResult(requestCode, resultCode, data);

 

        if(requestCode == 101 && resultCode == Activity.RESULT_OK) {

            BitmapFactory.Options options = new BitmapFactory.Options();

            options.inSampleSize = 8 ;

            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);

            imageView.setImageBitmap(bitmap);

        }

    }

 

위처럼 결과가 오면 사진은 capture.jpg에 저장 됬으므로 그 파일의 절대경로를 인자로 넘겨(옵션은 크기를 줄이기 위하여 넣어줌) 파일을 디코드 시켜 비트맵에 저장하여 다시 이미지 뷰에 저장해준다.

 

 

 

결과화면

 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

방법2(카메라 장치 이용)

 

MainActivity

...더보기
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
package com.example.boostcoursepractice;
 
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
 
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
 
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
 
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
 
import java.io.File;
import java.net.URL;
import java.util.HashMap;
 
public class MainActivity extends AppCompatActivity {
 
    ImageView imageView;
    CameraSurfaceView surfaceView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        imageView = (ImageView) findViewById(R.id.imageView);
        surfaceView = (CameraSurfaceView) findViewById(R.id.surfaceView);
 
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                capture();
            }
        });
 
 
    }
 
    public void capture() {
        surfaceView.capture(new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] bytes, Camera camera) {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 8 ;
                Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
 
                imageView.setImageBitmap(bitmap);
 
                camera.startPreview();
            }
        });
    }
}
cs

 

CameraSurfaceView

...더보기
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
package com.example.boostcoursepractice;
 
import android.content.Context;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
 
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
 
    SurfaceHolder holder ;
    Camera camera = null ;
 
    public CameraSurfaceView(Context context) {
        super(context);
 
        init(context);
    }
 
    public CameraSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
 
        init(context);
    }
 
    public void init(Context context)
    {
        holder = getHolder();
        holder.addCallback(this);
    }
 
    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
         camera = Camera.open();
 
         try{
             camera.setPreviewDisplay(holder);
         }catch (Exception e){
             e.printStackTrace() ;
         }
    }
 
    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
        camera.startPreview();
    }
 
    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        camera.stopPreview();
        camera.release();
        camera=null;
    }
 
    public boolean capture(Camera.PictureCallback callback)
    {
        if(camera != null)
        {
            camera.takePicture(nullnull, callback);
            return true ;
        }else{
            return false;
        }
    }
}
 
cs

 

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
26
27
28
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical">
 
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="사진찍기" />
 
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        app:srcCompat="@android:drawable/sym_def_app_icon" />
 
    <com.example.boostcoursepractice.CameraSurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>
 
cs

 

두번째 방법으로는 직접 카메라 장치를 이용하는 방법인데 이 때 SurfaceView를 이용한다. 여기서는 CameraSurfaceView라는 SurfaceView를 상속받은 클래스를 하나 만들어 주고 SurfaceHolder.Callback라는 인터페이스도 implement하였다. 이런 SurfaceView는 껍데기 역할만 해주는 것이고 실질적으로 동작하는 것은 SurfaceHolder가 해준다. 따라서 클래스안에 SurfaceHolder holder, Camera camera 같이 holder와 camera를 만들어 주었다.

 

 public void init(Context context)

    {

        holder = getHolder();

        holder.addCallback(this);

    }

 

일단 처음 뷰가 생성이 되면 init를 해주는데 holder에 홀더를 가져와 할당해주고 holder에 SurfaceHolder.Callback를 implement한 이 클래스를 콜백함수로 등록해 준다. 이 클래스는 SurfaceHolder.Callback에 등록된 surfaceCreatedsurfaceChanged, surfaceDestroyed를 오버라이드 해주었는데 여기서는 카메라를 열고 미리보기를 보여주고 클래스가 없어지면 할당을 해제해주는 함수를 등록해놓았다. 마지막으로 xml파일에 SurfaceView를 만들어 주고 메인액티비티로 돌아가 SurfaceView를 찾아 할당해주고 거기에 아래의 함수

 

public void capture() {

        surfaceView.capture(new Camera.PictureCallback() {

            @Override

            public void onPictureTaken(byte[] bytes, Camera camera) {

                BitmapFactory.Options options = new BitmapFactory.Options();

                options.inSampleSize = 8 ;

                Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);

 

                imageView.setImageBitmap(bitmap);

 

                camera.startPreview();

            }

        });

    }

 

를 호출해주어 그 매개 변수로 Camera.PictureCallback의 onPictureTaken오버라이드하여 생성하여 넘겨준다. 이제 미리보기 화면에서 카메라를 찍으면 byte로 넘어오고 그거 decode하여 bitmap으로 변환하여 이미지 뷰에 설정해주면 된다. 이 과정이 끝나면 미리보기가 끝나므로 다시 camera.startPreview()를 호출해주면 된다.

 

 

결과화면

 

MainActivity.java

 

NetworkStatus.java

 

activity_mai.xml

 

인터넷 연결 상태를 확인하기 위하여 NetworkStatus클래스를 하나 정의 해주자 그리고 아래와 같이 

 

ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE) ;

NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if(networkInfo != null)
{
int type = networkInfo.getType();
if(type == ConnectivityManager.TYPE_MOBILE)
{
return TYPE_MOBILE ;
}else if(type == ConnectivityManager.TYPE_WIFI) {
return TYPE_WIFI;
}
}

return TYPE_NOT_CONNECTED;

 

시스템서비스를 통해 매니저를 얻고 그 매저를 통해 네트워크 정보를 얻고 네트워크 정보에서 어떤 타입으로 연결되어 있는지 확인하여 지금 현재 핸드폰의 인터넷 연결 유형 또는 미연결 상태를 알아내는 함수를 만들어내주면 끝난다.

(매니페스트에 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 권한 추가필요)

 

 

결과화면

 

MainActivity

 

activity_main.xml

 

데이터베이스를 이용한 어플리케이션에서 만약 어플리케이션이 배포가 완료되고 다시 테이블의 칼럼이나 구성을 바꿔야할 상황일 때 이 헬퍼를 이용하면 편리하다. 우선 아래처럼

 

class DatabaseHelper extends SQLiteOpenHelper {

public DatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {

println("onCreate() 호출됨");

String tableName = "customer";

String sql = "create table if not exists " + tableName + "(_id integer PRIMARY KEY autoincrement , name text, age integer, mobile text) ";
sqLiteDatabase.execSQL(sql);

println("테이블 생성됨.");

}

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

println("onUpgrade() 호출됨" + i + ", " + i1) ;

if(i1 > 1)
{
String tableName = "customer" ;
sqLiteDatabase.execSQL("drop table if exists " + tableName);
}
}
}

SQLiteOpenHelper를 상속받은 클래스를 하나 정의 해주고 public void onCreate,  onUpgrade를 오버라이드 해주면 준비는 끝난다. 이 후 데이터베이스를 열 때 

 

DatabaseHelper helper = new DatabaseHelper(this, databaseName, null, 3 );
database = helper.getWritableDatabase();

 

이런 식으로 getWritableDatabase를 이용하여 열어 주면 된다. 이 때 데이터 베이스가 처음 생성되는 경우라면 onCreate가 실행되고 또는 데이터베이스가 버전이 업그레이드 되어 열리면 onUpgrade가 실행된다.(둘 다 아닐 경우 아무것도 실행안됨 그 이후에 onOpen() 무조건 실행됨) 이 두 메서드를 잘오버라이드 시켜 버전관리를 해주면 된다. 

 

 

 

결과화면

 

MainActivity

...더보기
  
package com.example.boostcoursepractice;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;

import android.util.Log;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import java.net.URL;
import java.util.HashMap;

public class MainActivity extends AppCompatActivity {

    EditText editText ;
    EditText editText2 ;
    EditText editText3 ;
    EditText editText4 ;
    EditText editText5  ;
    TextView textView;
    SQLiteDatabase database ;

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

        editText = (EditText) findViewById(R.id.editText);
        editText2 = (EditText) findViewById(R.id.editText2);
        editText3 = (EditText) findViewById(R.id.editText3);
        editText4 = (EditText) findViewById(R.id.editText4);
        editText5 = (EditText) findViewById(R.id.editText5);

        textView = (TextView) findViewById(R.id.textView);

        Button button = (Button) findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String databaseName = editText.getText().toString();
                openDatabase(databaseName);
            }
        });

        Button button2 = (Button) findViewById(R.id.button2);

        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String tableName = editText2.getText().toString();
                createTable(tableName);
            }
        });

        Button button3 = (Button) findViewById(R.id.button3);

        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String name = editText3.getText().toString().trim();
                String ageStr = editText4.getText().toString().trim();
                String mobile = editText5.getText().toString().trim();

                int age = -1 ;
                try{
                    age = Integer.parseInt(ageStr);
                }catch (Exception e) {
                    e.printStackTrace();
                }

                insertData(name, age, mobile);

            }
        });

        Button button4 = (Button) findViewById(R.id.button4);
        button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String tableName = editText2.getText().toString();
                selectData(tableName);
            }
        });
    }

    public void openDatabase(String databaseName)
    {
        println("openDatabase() 호출됨");
        database = openOrCreateDatabase(databaseName, MODE_PRIVATE, null);

        if(database != null)
        {
            println("데이터 베이스 오픈됨");
        }

    }

    public void createTable(String tableName)
    {
        println("crateTable() 호출됨");

        if(database !=null)
        {
            String sql = "create table " + tableName + "(_id integer PRIMARY KEY autoincrement , name text, age integer, mobile text) ";
            database.execSQL(sql);

            println("테이블 생성됨.");
        }else{
            println("먼저 데이터베이스를 오픈하세요");
        }
    }

    public void insertData(String name, int age, String mobile)
    {
        println("insertData() 호출됨");

        if(database != null)
        {
            String sql = "insert into customer(name, age, mobile) values(?,?,?)";
            Object[] params = {name, age, mobile};

            database.execSQL(sql, params);
            println("데이터 추가됨");
        }else{
            println("먼저 데이터베이스를 오픈하세요.");
        }
    }

    public void selectData(String tableName)
    {
        println("selectData() 호출됨");

        if(database != null)
        {
            String sql = "select name, age, mobile from " + tableName ;
            Cursor cursor = database.rawQuery(sql, null);
            println("조회된 데이터 개수 : " + cursor.getCount());

            for(int i=0 ; i<cursor.getCount() ; i++)
            {
                cursor.moveToNext();
                String name = cursor.getString(0);
                int age = cursor.getInt(1);
                String mobile = cursor.getString(2) ;

                println("#" + i + "->" + name + ", " + age + ", " + mobile);
            }

            cursor.close();
        }
    }


    public void println(String s)
    {
        textView.append(s+"\n");
    }

}
  

 

activity_mail.xml

 

우선 데이터 베이스를 구성하고 관리하는데는 4가지 단계가 있다. 데이터베이스를 1.오픈하고 2.테이블을 만들고 데이터를 3.추가하고 4.조회하고 일단 오픈 하는 코드는 

 

SQLiteDatabase database = openOrCreateDatabase(databaseName, MODE_PRIVATE, null);

 

위와 같고 테이블을 만들고 데이터를 추가할 때는 아래와 같이

 

String sql = "create table " + tableName + "(_id integer PRIMARY KEY autoincrement , name text, age integer, mobile text) ";
database.execSQL(sql); 

 

String sql = "insert into customer(name, age, mobile) values(?,?,?)";
Object[] params = {name, age, mobile};

database.execSQL(sql, params);

 

SQLiteDatabase의 execSQL()의 매개변수로 sql문을 넘겨 실행시킨다.

 

마지막으로 조회는 

 

String sql = "select name, age, mobile from " + tableName ;
Cursor cursor = database.rawQuery(sql, null);
println("조회된 데이터 개수 : " + cursor.getCount());

for(int i=0 ; i<cursor.getCount() ; i++)
{
cursor.moveToNext();
String name = cursor.getString(0);
int age = cursor.getInt(1);
String mobile = cursor.getString(2) ;

println("#" + i + "->" + name + ", " + age + ", " + mobile);
}

cursor.close();

 

위와 같이 SQLiteDatabase의 rawQuery()를 이용하여 리턴 값으로 Cursor를 받고 커서의 getCount()로 레코드의 개수를 파악하고 cursor.moveToNext()로 다음 레코드로 넘어가고 cursor.getString(0), cursor.getInt(1) 같은 것들로 현재 레코드의 얻고자하는 컬럼 번호를 지정하여 데이터를 가져와야 한다.

 

 

 

 

결과화면

MainActivity

...더보기
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
package com.example.boostcoursepractice;
 
import android.os.Bundle;
 
import android.view.View;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
 
public class MainActivity extends AppCompatActivity {
 
    TextView textView;
    ImageView imageView;
    Button button;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
 
        imageView = (ImageView) findViewById(R.id.imageView);
 
        button = (Button) findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendImageRequest();
            }
        });
    }
 
    public void sendImageRequest() {
        String url = "https://lh5.googleusercontent.com/p/AF1QipP88UCg_d5npMcxmBkm_ZXqmxm2korTx5Bdya9k=w237-h160-k-no";
        ImageLoadTask task = new ImageLoadTask(url, imageView);
        task.execute();
 
    }
}
cs

 

ImageLoadTask

...더보기
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
package com.example.boostcoursepractice;
 
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
 
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
 
public class ImageLoadTask extends AsyncTask<Void, Void, Bitmap> {
 
    private String urlStr ;
    private ImageView imageView ;
 
    private static HashMap<String, Bitmap> bitmapHash = new HashMap<String, Bitmap>();
 
    public ImageLoadTask(String urlStr, ImageView imageView)
    {
        this.urlStr = urlStr;
        this.imageView = imageView ;
    }
 
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
 
 
    }
 
    @Override
    protected Bitmap doInBackground(Void... voids) {
        Bitmap bitmap = null ;
        try{
            if(bitmapHash.containsKey(urlStr))
            {
                Log.d("jjh""해쉬에 있음");
                Bitmap oldBitmap = bitmapHash.remove(urlStr);
                if(oldBitmap !=null)
                {
                    oldBitmap.recycle();
                    oldBitmap = null;
                }
            }
 
            URL url = new URL(urlStr);
            bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
 
            bitmapHash.put(urlStr, bitmap);
        }catch (Exception e){
            e.printStackTrace();
        }
 
        return bitmap;
    }
 
    @Override
    protected void onProgressUpdate(Void... values) {
        super.onProgressUpdate(values);
    }
 
    @Override
    protected void onPostExecute(Bitmap bitmap) {
        super.onPostExecute(bitmap);
 
        imageView.setImageBitmap(bitmap);
        imageView.invalidate();//다시 그려주는 메서드인데 UI객체는 일부로 할 필요는 없지만 혹시나 해서 해줌
    }
}
 
cs

 

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical">
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
 
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="이미지 가져오기" />
 
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="100dp"
            android:layout_height="100dp"
            app:srcCompat="@android:drawable/btn_star_big_on" />
    </LinearLayout>
 
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_orange_light">
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
 
            <TextView
                android:id="@+id/textView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="18dp" />
        </LinearLayout>
    </ScrollView>
 
</LinearLayout>
 
cs

 

일단 여기서는 웹에 있는 이미지를 가져오기 위해 그냥 일반적인 스레드 방식으로 비트맵 방식으로 이미지를 가져오고 내부적으로는 핸들러를 이용해서 UI를 바꾸는 방법으로 구현하였다. 중간 코드에 밑에 처럼

 

if(bitmapHash.containsKey(urlStr))

            {

                Log.d("jjh""해쉬에 있음");

                Bitmap oldBitmap = bitmapHash.remove(urlStr);

                if(oldBitmap !=null)

                {

                    oldBitmap.recycle();

                    oldBitmap = null;

                }

            }

 

            URL url = new URL(urlStr);

            bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());

 

            bitmapHash.put(urlStr, bitmap);

 

이러한 코드가 있는데 메모리에 비트맵 이미지를 올리고 또 버튼을 클릭하여 이미지를 가지고 올 때 메모리의 이미지가 안사라지고 또 이미지가 올라가는 경우가 생기면 메모리 용량을 많이 차지하는 문제가 생길 수 있으므로(내 생각에는 자바에서 그냥 이미지 비트맵을 가리키는 변수가 없어지기 때문에 자동으로 버릴거 같은데 혹시 모르니까 해주는 거 같다.) url 과 비트맵을 키,값을 가지는 해쉬맵으로 관리하여 쓰였던 url 이면 전에 있던 그 url의 해당하는 비트맵을 recycle즉 없애 주는 코드도 추가하였다.

 

 

 

***************************중요*********************************

1. 자바에서는 HashMap, ArrayList등 이런 컨테이너 인터페이스로 구현해놓은 것들에 원소를 추가 해줄 때 그 대상이 객체이면 객체를 복사하는 것이 아니라 참조자만 가지고 관리한다.(그래서 원래 객체의 값을 변경하면 실제 컨테이너 내부의 객체도 변경된다.)

 

2.AsyncTask의 onPreExecute, onPostExecute에서도 UI접근이 가능하다. 즉 핸들러큐에 들어간다는 얘기인데 뭔가 onPreExecute에서만 핸드러큐에 들어가서 원래 메인 스레드의 진행을 중지하고 핸들러의 큐를 먼저 실행시켜주는 듯 하다?(이건 확실하지가 않다 지금까지 실험해본 결과로는 onPreExecute가 핸들러 큐에 들어가는 건 확실한데 내 생각에는 본래 진행되던 메인 스레드의 진행이 다 끝나고 진행되어야 하는데 갑자기 핸들러가 진행된다. 아직 의문이다 이건 언젠가 아는날이 오지 않을까...?)

 

 

결과화면

 

+ Recent posts