간단히 사진 찍기

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


  1. 불필요한 객체 생성을 하지마라
  2. 객체의 필드를 사용하지 않는 다면 Static을 사용해라
    • Static이 15~20% 빠르다.
  3. 상수는 Static Final로 선언해라
  4. 클래스 내부에서 Getters/Setters를 사용하지마라
    • 객체의 필드에 직접 접근하는 것이 빠르다. (Without JIT 3배, With JIT 7배)
    • 하지만, Proguard를 사용하는 경우 어떻게 해도 관계없이 빠르다. (inline으로 대체)
  5. Enhanced For Loop를 우선적으로 사용해라
  6. 내부 클래스도 고려하여 접근 제한자를 설정해라
  7. 부동소수점(Float, Double) 자료형을 가급적 사용하지마라
    • 안드로이드 시스템에서 정수형보다 약 2배 느리다.
  8. 메소드를 직접 만들지 말고, 라이브러리에 있는 것을 사용해라
  9. NDK를 통한 Native 메소드 사용은 속도 개선에 도움을 주지 않는다
    • Java-Native간 호출에 시간이 걸리며, JIT가 최적화 할 수도 없다.
  10. 성능 관련 속설들
    • 인터페이스 사용이 느리다? => Without JIT에서 6%정도 느리지만, With JIT에서는 차이가 미미하다.
    • 필드에 접근하는 것이 로컬 변수에 접근하는 것보다 느리다? => Without JIT에서는 20%정도 느리지만, With JIT에서는 동일하다.
  11. 항상 측정하라


설정

트랙백

댓글

프로젝트 리더(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)할 수 있어야 함.


출처 : 신기술창업지원단

설정

트랙백

댓글