2016년 3월 24일 목요일

바코드스캐너#안드로이드 해상도와 무관하게 스캔영역 넓히기



바코드스캐너
#안드로이드 해상도와 무관하게 스캔영역 넓히기



소스)

CameraManager.java

/**
   * Calculates the framing rect which the UI should draw to show the user where to place the
   * barcode. This target helps with alignment as well as forces the user to hold the device
   * far enough away to ensure the image will be in focus.
   *
   * @return The rectangle to draw on screen in window coordinates.
   */
  public synchronized Rect getFramingRect() {
  if (framingRect == null) {
      if (camera == null) {
        return null;
      }
      Point screenResolution = configManager.getScreenResolution();
      int width = screenResolution.x * 3 / 4;
 
      int height = screenResolution.y * 3 / 4;
      Log.v("Framing rect is : ", "width is "+width+"   and height is "+height);
      int leftOffset = (screenResolution.x - width) / 2;
      int topOffset = (screenResolution.y - height) / 2;
      framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
      Log.d(TAG, "Calculated framing rect: " + framingRect);
  }
  return framingRect;

  /*if (framingRect == null) {
      if (camera == null) {
        return null;
      }
      Point screenResolution = configManager.getScreenResolution();
      if (screenResolution == null) {
        // Called early, before init even finished
        return null;
      }
      int width = findDesiredDimensionInRange(screenResolution.x, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
      int height = findDesiredDimensionInRange(screenResolution.y, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);
      int leftOffset = (screenResolution.x - width) / 2;
      int topOffset = (screenResolution.y - height) / 2;
      framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
      Log.d(TAG, "Calculated framing rect: " + framingRect);
      }
      return framingRect;*/
  }

* 해상도와 무관하게 스캔의 영역을 넓혀줘요

==========================================

소스) 캡춰 화면



* 안드로이드 어플중에 대만에서 만든 바코드 스캐너, 큐알스캐너 어플이 있는데, 아주 심플하지만  인기가 좋은  이유가 있었다,
지인중에 기획력이 뛰어난 분이 면밀히 검토한 결과 발견했는데, 미묘한 차이점 중 하나가 스캔영역을 넓혀주니 스캔이 잘되게 해주는 편리함을 제공해주니 인기가 좋다,,,
이외에  간단하면서도 군더더기가 없었던게 인기의 비결이었다고 해요

- 안드로이드 어플 개발하는데 있어서의 핵심 포인트는 편리함과 안정성

즐거운 시간 보내세요~

2016년 3월 11일 금요일

안드로이드강좌 > 멀티쓰레드(Multi Thread) 를 손쉽게 구현해보자



안드로이드 강좌 > 멀티쓰레드 소스

멀티쓰레드(Multi Thread)는 프로세스(Process)안에서 여러개의 쓰레드가 동시에 동작하는것이다.
하나의 프로세스에 쓰레드가 여러개로 보면 된다.
마치 한컴퓨터에 여러개의 프로그램이 돌아가는거라보면 보면 여기서 한컴퓨터는 프로세스입장이고, 여러개의 프로그램은 쓰레드의 입장이라 보면 되겠다

java 1.5 버전 부터 java.util.concurrent 패키지가 생김으로 인해 멀티 쓰레드 프로그래밍을 손쉽게 구현할 수 있어요
예전에는 구현하기가 복잡했지만, 현재는 아주 간단하게 구현이 가능하다. 여러분은 쓰레드에 대한 몇가지 요소만 배우시면 돼요 
자바를 실행하면 main 쓰레드라 불리우는 것이 해당 객체의 main(String[]) 메소드를 실행해줘요
즉, 프로그램이 실행되면, 최소한 한 개 이상의 쓰레드는 동작한다 보시면 돼요

제목 : Multi Thread를 손쉽게 구현해보자




첫째. Thread 생성 및 실행
Thread 생생은 java.lang.Runnable 인터페이스를 이용하시거나, java.lang.Thread를 상속받아서 구현하는 방법이 있어요
여기서 생성한 Thread를 start() 메소드를 이용해서 작동시켜준다. 
이 메소드가 호출되면 자동으로 run()메소드가 실행이 된다. 
그래서 어떤 작업을 하고 싶으면, run() 메소드 안에 해당 작업을 구현해주면 된다

예제)
package test.thread;  

public class SimpleThread extends Thread {  
     public void run() {  
         for (int i = 0; i < 10; i++) {  
             System.out.printf("[%s] %d번째 : %n", Thread.currentThread().getName(), i);  
         }
     }
     
     public static void main(String[] args) throws InterruptedException {  
         Thread threadOne = new SimpleThread();  
         Thread threadTwo = new SimpleThread();  
         threadOne.start();
         threadTwo.start();
     }
 }

 =============================

둘째. 동기화
 - 기본적인 개념은 "volatile 에 대한 단상"(http://blog.kangwoo.kr/43)을 참고 바란다.
 - java.util.concurrent.Semaphore 클래스를 이용하면 자원 사용을 제어
   즉, 사용할 수 있는 자원이 최대 N개인데, N개보다 많은 수의 쓰레드가 그 자원을 필요로 할 경우 제어
 - java.util.concurrent.locks.ReentrantLock : 읽기/쓰기 락을 제어

셋째. Executor를 이용하여 Thread를 관리해준다
  - 보통 자원의 효율적 이용을 위해서 Thread Pool과 Queue를 만들어서 사용한다
  자바 1.5에서는 기본적으로 지원해준다. 
  java.util.concurrent.Executors을 이용하면 아주 손쉽게 사용할 수 있어요
   + java.util.concurrent.TimeUnit : 시간 단위를 나타낸다. 
     DAYS, HOURS, MICROSECONDS, MILLISECONDS, MINUTES, NANOSECONDS, SECONDS 가 있다.

   + java.util.concurrent.Executor : 처리할 작업을 실행할 수 있는 기능을 정의해준다
     + execute(Runnable) : 해당 작업을 실행한다. 
   쓰레드 풀이 구현된경우에는 전달받은 작업을 큐(Queue)에 넣은 후, 가용 쓰레드가 존재할 경우 작업을 실행한다

   + java.util.concurrent.ExecutorService : 
     Executor의 하위 인터페이스로서 생명주기(shutdown(), shutdownNow()를 관리할 수 있는 기능과 
     Callable을 사용할수 있는 기능을 정의하고 있다. 
     + shutdown() : 중지(shutdown) 명령을 내린다. 
   대기중인 작업은 실행되지만, 새로운 작업은 추가되지 않는다.
     + List<Runnable> shutdownNo() : 현재 실행중인 모든 작업 및 대기중인 작업 모두를 중지시킨다. 
   대기중인 작업 목록을 반환한다.
     + boolean isShutdown() : Executor가 중지(shutdown)가 되었는지 여부를 판단한다.
     + boolean isTerminated() : 모든 작업이 종료되었는지 여부를 판단한다.
     + boolean awaitTermination(long, TimeUnit) : 
   중지(shutdown) 명령을 내린후, 지정한 시간 동안 모든 작업이 종료될때까지 대기한다. 
   지정한 시간이내에 작업이 종료되면 true, 아니면 false를 반환한다.
     + Future submit(Callable task) : 결과값을 반환할수 있는 Callable 작업을 실행한다. 
   (Callable에 대해서는 뒤에서 다루겠다.)

   + java.util.concurrent.ScheduledExecutorService : 
     ExecutorService의 하위 인터페이스로서 스케줄에 따라 작업을 실행할 수 있는 기능을 정의하고 있다.
     + ScheduledFuture<?> schedule(Runnable, long, TimeUnit)  : 지정한 시간 이후에 작업을 실행한다.
   
   + java.util.concurrent.Executors : 
      자바 1.5에서 기본적으로 제공하는 Executor 구현체를 생성할 수 있는 메소드를 제공하는 유틸리티 클래스이다.
     + ExecutorService newFixedThreadPool(int) : 지정한 갯수만큼 쓰레드를 가질 수 있는 쓰레들 풀을 생성한다. (ThreadPoolExecutor)
     + ExecutorService newCachedThreadPool() : 재사용이 가능한 쓰레드 풀을 생성한다. (ThreadPoolExecutor)
     + ExecutorService newSingleThreadExecutor() : 단일 쓰레드만을 사용하는 ExecutorService 를 생성한다.
  + ScheduledExecutorService newScheduledThreadPool(int) : 
     스케줄 가능한 쓰레드 풀을 생성한다. (ScheduledThreadPoolExecutor)
     + ScheduledExecutorService newSingleThreadScheduledExecutor() : 
       단일 쓰레드만을 사용하는 스케줄 가능한 ExecutorService 를 생성한다.

   + java.util.concurrent.ThreadPoolExecutor
   
   + java.util.concurrent.ScheduledThreadPoolExecutor

> Executors 클래스를 가지고 간단한 멀티 쓰레드 프로그램 예제

package test.thread;  

import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  

public class MultiThreadUnit implements Runnable {  
     private int total;  
     public void run() {  
         for (int i = 1; i <= 30000; i++) {  
             total += i;  
         }  
         System.out.printf("[%s] 1에서 30000까지의 총 합은 %d : %n", Thread.currentThread().getName(), total);  
     }

 public static void main(String[] args) throws InterruptedException {  
         ExecutorService extService = Executors.newFixedThreadPool(3);  
         extService.execute(new MultiThreadUnit());
         extService.execute(new MultiThreadUnit());
         extService.execute(new MultiThreadUnit());
         extService.execute(new MultiThreadUnit());
         extService.execute(new MultiThreadUnit());
         extService.execute(new MultiThreadUnit());
         extService.execute(new MultiThreadUnit());
         extService.execute(new MultiThreadUnit());
         extService.shutdown();
     }
 }

> 출력 결과
[pool-1-thread-1] 1에서 20000까지의 총 합은 300010000
[pool-1-thread-2] 1에서 30000까지의 총 합은 300010000
[pool-1-thread-3] 1에서 30000까지의 총 합은 300010000
[pool-1-thread-1] 1에서 30000까지의 총 합은 300010000
[pool-1-thread-2] 1에서 30000까지의 총 합은 300010000
[pool-1-thread-3] 1에서 30000까지의 총 합은 300010000
[pool-1-thread-1] 1에서 30000까지의 총 합은 300010000
[pool-1-thread-2] 1에서 30000까지의 총 합은 300010000

> 위의 출력결과처럼 잘 돌아간다 : 아주 심플해서 편해요

* 참고로, 
  해당 데몬(daemon)이 종료되면, 
  더 이상을 요청을 받아서는 안된다. 그리고 기존에 받은 요청은 지정한 시간내에 끝내야한다
  이 경우에 아래처럼 구현할 수 있어요

소스)
void shutdownAndAwaitTerminate(ExecutorService pool) {  
   pool.shutdown();
   try {  
     if (!pool.awaitTermination(50, TimeUnit.SECONDS)) {  
       pool.shutdownNow();
       if (!pool.awaitTermination(50, TimeUnit.SECONDS))  
           System.err.println("Pool이 끝나지 않았다");  
     } 
   } catch (InterruptedException ie) {
     pool.shutdownNow();
     Thread.currentThread().interrupt();
   }
 }

여기서 일단락 마무리하고 다음

=======================================================

> Callabe로 쓰레드 구현하기
  참고사항 : Callable 인터페이스의 call() 메소드는 결과값을 반환하도록 구성돼있어
  하지만 call() 메소드를 이용해서 결과값을 반환받을때까지 기다리면, 그건 효용가치가 떨어진다
  그래서 이럴경우 Future 인터페이스를 사용한다

package test.thread;  

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.Future;  

public class MultiThreadUnit implements Callable<INTEGER> {  
     private int total;  
     public Integer call() throws Exception {  
         for (int i = 1; i <= 30000; i++) {  
             total += i;  
         }  
         return total;  
     }

 public static void main(String[] args) throws InterruptedException, ExecutionException {  
         ExecutorService exctService = Executors.newFixedThreadPool(3);
         Future<INTEGER> ft1 = exctService.submit(new MultiThreadUnit());
         Future<INTEGER> ft2 = exctService.submit(new MultiThreadUnit());
         Future<INTEGER> ft3 = exctService.submit(new MultiThreadUnit());

         System.out.printf("[%s] 1에서 30000까지의 총 합은 %d : %n", "ft1", ft1.get());  
         System.out.printf("[%s] 1에서 30000까지의 총 합은 %d : %n", "ft2", ft2.get());  
         System.out.printf("[%s] 1에서 30000까지의 총 합은 %d : %n", "ft3", ft3.get());  
         exctService.shutdown();  
     }

예전에 비하여 구현하기가 많이 편리해졌어요
시간이 지나면 지날수록 개발이 편리해져요
개발하는것도 날아갈수록 발전되어야 하는데, 한사람이 모두 신기술을 마스터하기는 힘들다...
후손들에게 하나씩 전수해줘야지 ^^

즐거운 시간 보내세요~


2016년 3월 5일 토요일

이상적인길#경기도 여주에서 사포영업 하시는 분의 삶


이상적인길
#경기도 여주에서 사포영업 하시는 분의 삶




안드로이드 어플 개발 문의가 있어서 전화 통화를 하게 됐어요
KJY<= 나이는 30대 고향은 전라북도 광주이고 군대다녀오고 서울에서 영어를 전공해서 학원강사도 하고 여러가지를 해오다가 근래에 경기도 여주에서 사포(나무 목재를 맨들하게 만들어주는 공사도구)영업을 한다고 해요
그러나 기쁘고 만족해야 하는데, 그렇지 못하여 이직을 준비하고 있다고 해요

이직준비를 하면서 안드로이드 어플을 개발하고 싶다고  해요

소개팅어플
서비스를 만들어서 운영을 하는데 있어서 초기에 안착이 상당부분 중요하다
인지도를 쌓기까지가 중요하다
소개팅의 중요한 부분중의 하나가 신뢰이다
초기에 어떻게 사람(유저)을 모집을 할것인가가 중요하다
마케팅에 있어서 확신이 있어도 실제 시점에서는 어려운 부분이 있다
KJY은 현재는 공부중이다

많으면 100년정도의 삶을 사는데, 하나님이 사람을 지으실 때 사랑하기 때문에 지으시고, 사랑하기 때문에 잘, 기쁘게 보람되게 살기를 원하신다.
그러나 현재 지구에 73억명정도가 살고 있어요
이 인구중에 진정 기쁘게 보람되게 사는 분들보다 허다한 사람들이 안타깝게 그리살지 못하고 있어요
(말씀을 잘  전하시는 분의 말씀)

기쁘게 보람되게 즐겁게 살려면 어떻게 해야할까 <= 많은 사람들이 한번정도는 구상을 해보는 부분
각기 좋다고 보는 부분의 일을 선택해서 길을 가게 돼요
자기 적성에 맞는 일을 찾아야 하는데, 현실적으로 그리 쉬운 부분은 아니라고 해요

경기도 여주에서 일하시는  KJY분도 시작은 좋았다
그러나 과정중에 방향전환을 여러번 하셨어요
영어강사 다른 일, 그리고 사포의 일에 이르기까지
이직을 준비중이며 안드로이드 어플도 개발공부를 하고 있어요

초기부터 이상적인 길을 선택을 했으면 한길로 주~ㄱ 가는데, 이상적인 길을  선택하는 것은 그리 쉬운 일은 아니다
그래서 멘토가 필요하다

지인중에 기획과 마케팅쪽에 전문가 분이 있는데, 이 분도 현재 하고 있는 분야에 있어서 멘토가 있으면 얼마정도 절약을 하셨을거 같냐고 문의를 하니 대략 5년정도 이상은 절약을 했을거라 얘기를 하신다

아는것이 그리 중요하다
그래서 말씀 잘 전하시는 목사님이 말씀하시기를 "알고 행해"라는 중요한 말씀도 전해주셨어요
보이는 육의 세계도 보이지  않는 세계도 알고 사는것이 그리중요해요

KJY도 조만간 멘토를 만나서 미처 발견하지 못한 가치를 발견하게 될듯 해요

2016년 3월 4일 금요일

바코드스캐너#back button 클릭시의 이벤트 처리, dispatchKeyEvent


바코드스캐너
#back button 클릭시의 이벤트 처리, dispatchKeyEvent



대부분의 어플이 onKeyDown 이벤트가 동작을 잘하지만 zxing을 활용은 어플은 back button click 되었을 시 사이트의 사운드 키나 메뉴키가 터치된 경우에 동작을 하지만 취소 키가 터치된 경우에는 반응을 하지 않는다, 이 경우 해결 방법이 구글링을 해보니 방법이 나와 있다, dispatchKeyEvent가 바코드스캐너 어플에서 동작이 가능하게 해준다
barcode scanner에서 종료시 광고를 띄우거나 리뷰로 유도하기 위하여 back button 터치이벤트를 활용하는데, 이 dispatchKeyEvent를 활용해서 개발하시면 유용해요

소스)
  @Override
  public boolean dispatchKeyEvent(KeyEvent event) {
      
      switch (event.getKeyCode()) {
      case KeyEvent.KEYCODE_BACK:
    
      finish();
        break;
      case KeyEvent.KEYCODE_FOCUS:
      case KeyEvent.KEYCODE_CAMERA:
        return true;
      case KeyEvent.KEYCODE_VOLUME_DOWN:
       execFlash();
       return true;
      case KeyEvent.KEYCODE_VOLUME_UP:
       execFlash();
       return true;
  }
      
      return true;
  }

소스) 이미지


방문해주셔서 감사해요
즐거운 시간 보내세요~

2016년 3월 3일 목요일

바코드스캐너#다국어버전 개발에 필요한 R.string을 String으로 변환하기


바코드스캐너

#다국어버전 개발에 필요한 R.string을 String으로 변환하기



다국어버전 어플을 만들 경우에도 사용돼요


자바소스
String sUnitUpdateInfo = getResources().getString(R.string.update_info);
String sUnitRateReview = getResources().getString(R.string.rate_review);
String sUnitCreateQr = getResources().getString(R.string.create_qr);

...

xml 파일 (strings.xml)

<string name="update_info">Update</string>
<string name="rate_review">Rate and Review</string>
<string name="create_qr">Create QR</string>


values/strings.xml
values-ko/strings.xml
...


즐거운 시간 보내세요~




2016년 3월 1일 화요일

안드로이드 강좌 - 서울 (셋팅 + gcm 푸시강좌)




안드로이드 강좌를 해요

미션 : 
노트북에 안드로이드 개발을 위한 환경설정 및 삼성폰에 
샘플 gcm 푸시서비스 어플을 만들어서 배포하는 부분까지의 강좌를 진행해요
    강좌를 위한 프로그램들은 모두 준비가 되어 있어요
    Android SDK까지 준비가 되어 있어요(10기가 이상분량)
    프로그램(이클립스, Android SDK, Jdk1.7, 삼성 Kies)

수강료 : 
    3 마ㄴ 워ㄴ 

연락처 : 
    010 8676 7289 로 연락주세요~

이메일 : 
    mentor007angel@gmail.com

장소 : 
    서울 은평구 녹번동이거나 응암동 (인근 전철 : 녹번역, 응암역, 역촌역)

준비사항 : 
    노트북(20~30기가정도 여유 공간이 있는 하드디스크)+수강료

강좌잇점 : 
    1. 개발환경이 갖추어져서 여러 안드로이드 어플을 만드시는 준비작업이 다 갖추어져요
    2. Android SDK 실행 후에 각 버전 Download해서 Install하는데는 많은 시간이 소요되며,
       용량도 몇 기가에 이르기까지 많은 시간이 소요되지만 이미 수 기가에 이르는 프로그램을
       다운로드해서 설치가 된 상황이라서 시간이 따로 소요될 필요가 없어요
    2. 안드로이드 gcm 푸시서비스 어플 개발에 대한 소스가 생겨요
      (다른 하이브리드 어플을 개발하실 때는 커스터마이징해서 사용하시면 시간이 단축이 돼요)

상황이 되는 경우 추가 : 신앙에 기반을 둔 말씀을 잘 전하시는 목사님의 설교내용도 전해드려요
(주제 : 어떻게 하면 인생을 훌륭히 살 수 있는 지에 대한 방법)

----------

즐거운 시간 보내세요~