글
간단히 사진 찍기
Android
2014. 1. 29. 09:26
아래의 퍼미션이 필요하다.
<manifest ... >
<uses-feature android:name="android.hardware.camera"
android:required="true" />
...
</manifest>
- 만약 required를 false로 한다면, Runtime에 hasSystemFeature(PackageManager.FEATURE_CAMERA)를 통해 카메라가 사용 가능한지 알아볼 수 있다.
간단히 내장 카메라 앱을 통해 사진을 찍으려면 아래와 같이 한다. (resolveActivity 체크를 해야 앱이 죽는 걸 방지할 수 있다)
static final int REQUEST_IMAGE_CAPTURE = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
(내장 카메라 앱) 썸네일을 얻기 위해서는 아래와 같이 결과를 받는다.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
mImageView.setImageBitmap(imageBitmap);
}
}- 다른 앱과 공유해도 되는 사진의 경우 아래 메소드로 얻을 수 있는 경로에 저장하는 것을 권장한다.
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); - 다른 앱과 공유하면 안되는 사진의 경우 getExternalFilesDir()로 얻을 수 있는 경로에 저장하는 것을 권장한다. 이 경로는 앱 삭제시에 함께 삭제된다.
- 외장 저장 장치의 경우 아래의 퍼미션이 필요하다. (Android 4.4 부터는 별도의 퍼미션이 필요없다. 타 앱에서 접근 하지 못함)
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
...
</manifest> - 파일명 중복을 방지하도록 임시 파일을 생성하려면, 아래와 같은 방식을 추천한다.
String mCurrentPhotoPath;
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
return image;
} - (내장 카메라 앱) 이제 전체 사진을 위에 만든 임시 파일에 받아오자!
static final in REQUEST_TAKE_PHOTO = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
...
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
} - 한정된 메모리로 전체 사진을 로드하면, Out of Memory가 발생할 수 있다. 메모리 사용량을 줄이기 위해서 아래와 같은 방법을 사용하면 좋다.
private void setPic() {
// Get the dimensions of the View
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
mImageView.setImageBitmap(bitmap);
}
출처 : http://developer.android.com/
글
오디오 제어
Android
2014. 1. 28. 08:45
재생/볼륨 컨트롤
- 어떤 Audio Stream을 사용할지 선택한다. 일반적인 음악 재생은 STREAM_MUSIC을 선택한다. [다른 옵션 보기]
- 하드웨어 볼륨키는 현재 재생중인 것을 컨트롤한다. (재생중인 것이 없을 때는 전화벨 볼륨 조절)
특정 Audio Stream의 볼륨을 조절하고 싶다면 아래와 같이 한다. setVolumeControlStream(AudioManager.STREAM_MUSIC);
- 하드웨어 컨트롤키(블루투스 헤드셋등에 있는)를 제어하기 위해서는 아래와 같이 한다.
<receiver android:name=".RemoteControlReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>public class RemoteControlReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()) {
// Handle key press.
}
}
}
}만약, 코드상에서 Receiver를 등록/해제하려면 아래와 같이 한다.
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...
// Start listening for button presses
am.registerMediaButtonEventReceiver(RemoteControlReceiver);
...
// Stop listening for button presses
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);그런데, BroadcastReceiver는 일반적으로 Activity/Fragment등이 Invisible될 때 해제되므로 문제가 있다 (아래 내용에서 해결)
Audio Focus
- 여러개의 앱들이 모두 음악을 재생하고자 하면 문제가 있기 때문에, 안드로이드 시스템에서 제어를 해야한다.
Focus를 가지고 오기 위해서는 아래와 같이 한다.
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
// Use the music stream.
AudioManager.STREAM_MUSIC,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
am.registerMediaButtonEventReceiver(RemoteControlReceiver);
// Start playback.
}Focus를 반납하려면 아래와 같이 한다.
// Abandon audio focus when playback complete
am.abandonAudioFocus(afChangeListener)"Ducking" - Focus를 잃어도(다른 앱이 요청시) 계속 재생을 하고 싶다면 , Focus를 가져올때 아래와 같이 한다.
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
// Use the music stream.
AudioManager.STREAM_MUSIC,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// Start playback.
}- Focus의 변화에 따라 아래와 같이 대응한다.
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT
// Pause playback
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Resume playback
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
am.abandonAudioFocus(afChangeListener);
// Stop playback
}
}
}; - Duck 상태에서는 아래와 같이 대응한다.
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
// Lower the volume
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Raise it back to normal
}
}
};
재생되는 오디오 기기에 대해
현재 재생 가능한 기기를 알아보기 위해서는 아래와 같이 한다. (AudioManager의 메소드)
if (isBluetoothA2dpOn()) {
// Adjust output for Bluetooth.
} else if (isSpeakerphoneOn()) {
// Adjust output for Speakerphone.
} else if (isWiredHeadsetOn()) {
// Adjust output for headsets
} else {
// If audio plays and noone can hear it, is it still playing?
}- 재생되던 기기의 변경이 일어났을 때 처리는 아래와 같이 한다. (특히, 이어폰을 빼거나 블루투스를 껐을때)
private class NoisyAudioStreamReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
// Pause the playback
}
}
}
private IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private void startPlayback() {
registerReceiver(myNoisyAudioStreamReceiver(), intentFilter);
}
private void stopPlayback() {
unregisterReceiver(myNoisyAudioStreamReceiver);
}
출처 : http://developer.android.com/
글
안드로이드 성능 개선 팁 요약
Android
2013. 1. 18. 18:28
- 불필요한 객체 생성을 하지마라
- 객체의 필드를 사용하지 않는 다면 Static을 사용해라
- Static이 15~20% 빠르다.
- 상수는 Static Final로 선언해라
- 클래스 내부에서 Getters/Setters를 사용하지마라
- 객체의 필드에 직접 접근하는 것이 빠르다. (Without JIT 3배, With JIT 7배)
- 하지만, Proguard를 사용하는 경우 어떻게 해도 관계없이 빠르다. (inline으로 대체)
- Enhanced For Loop를 우선적으로 사용해라
- 내부 클래스도 고려하여 접근 제한자를 설정해라
- 부동소수점(Float, Double) 자료형을 가급적 사용하지마라
- 안드로이드 시스템에서 정수형보다 약 2배 느리다.
- 메소드를 직접 만들지 말고, 라이브러리에 있는 것을 사용해라
- NDK를 통한 Native 메소드 사용은 속도 개선에 도움을 주지 않는다
- Java-Native간 호출에 시간이 걸리며, JIT가 최적화 할 수도 없다.
- 성능 관련 속설들
- 인터페이스 사용이 느리다? => Without JIT에서 6%정도 느리지만, With JIT에서는 차이가 미미하다.
- 필드에 접근하는 것이 로컬 변수에 접근하는 것보다 느리다? => Without JIT에서는 20%정도 느리지만, With JIT에서는 동일하다.
- 항상 측정하라
글
프로젝트 리더(PL)의 역할과 자질
컴퓨터 일반
2010. 4. 18. 15:14
프로젝트리더의 5가지 역할
1. 전략적 기획가(Strategic Planner)
-프로젝트 목표와 비전 설정
-목표달성을 위한 전략계획 수립
-연구업무와 연구원의 연계(Matching) 및 프로젝트 추진일정(Scheduling)
2. 동기부여자(Exciter)
-팀 응집력, 팀정신(Team Spirit)의 구축
-팀 구성원들에 대한 Empowering(신바람)
3. 기술적 전문가(Technical Expert)
-신선한 아이디어나 새로운 접근방법에 대한 제안
-기술적 문제점 파악과 대안있는 비판
-다양한 아이디어, 접근방법, 시각들을 통합
-개개인의 아이디어나 연구결과에 대한 피드백
4. 기술정보통(Gatekeeper)
-활발한 외부 기술정보원접촉과 Networking
-시장 및 수요자 욕구에 대한 민감한 탐색(Monitoring)
-의사소통의 구심점 역할(Communication Star)
-경우에 따라서는 대변인이나 통역 역할
5. 열성적 추진자(Champion)
-프로젝트 목표와 리더개인 목표의 합일
-프로젝트의 열성적 추구자
-프로젝트 실행을 위한 승인과 자원획득
-관련부서와의 제휴 및 연대구축
-대외적인 홍보와 Salesman 역할 (Ambassador)
프로젝트리더의 자격요건
-주인의식(Ownership)이 있어야 함.
-하고 있는 일에 전적으로 몰입하고 사명감이 있어야 함.
-성공을 위한 강한 에너지와 열정(Need for Achievement)이 있어야 함.
-부문별 목표보다는 조직전체를 생각하는 팀정신 소유자(Team Player)
-자유로운 의사소통(Communicator)을 할 수 있어야 함.
-거시적 안목에서 일을 처리할 수 있는 자신감(Confidence)이 있어야 함.
-팀원들을 격려하고 도와주며 활력을 줄 수 있어야(Empowerment) 함.
-팀원을 관리하기 보다는 계발, 육성(Develop)할 수 있어야 함.
출처 : 신기술창업지원단