2016년 4월 1일 금요일

요리레시피(R) - 다양한 요리레시피들의 유투브 영상이 있는 안드로이드 어플을 소개해드려요~






이 요리레시피앱의 표지디자인에 나오는 요리사의 함박웃음이 어플의 퀄리티를 높여주고 있어요
따뜻한 느낌의 배경색과 요리사의 함박웃음, 요리가  일품이라고 엄지손가락으로 넘버1이라고 제스쳐도하고 자부심이 대단한 요리사임을 뽐내고 있어요

이 요리레시피 안드로이드 어플에는 다양한 요리 레시들이 있어요
유투브 영상으로 요리레시피들을 보실 수 있어요

요리레시피(R) - 디저트, 생선, 샐러드, 제빵/제과, 불고기에 대한 다양한 레시피들이 있어요
다국어 지원
한국어, 영어, 태국어, 인도(힌두어)
유투브 데이타 API를 이용하여 제작되었어요
즐거운 시간 보내세요~

[요리레시피 영상 카테고리]
채식, 요리비결, 한우, 셰프, 요리팁, 동영상요리팁, 최고의요리비결, 치킨, 돼지고기, 빵, 스파게티, 피자, 소고기, 고등어, 셀러드, 쿠키, 토마토, 달걀, 햄버거, 샌드위치, 아이스크림레시피, 요거트레시피, 감자레시피, 케잌레시피
[어류=생선 영상 카테고리]
우럭매운탕, 레몬소스 연어구이, 북어 매운양념구이, 낙지한마리 생태탕, 병어튀김, 참치 샌드위치, 양념 갈치구이, 회덮밥, 고추참치, 호박씨 멸치볶음, 대구양념장구이, 임연수구이, 민어매운탕, 묵은지 고등어찜, 고등어 유자소스구이, 둥근호박 갈치조림, 꽁치찌개, 삼치 간장구이, 연어아보카도 샐러드, 장어계란덮밥, 아몬드 멸치볶음, 콩나물 참치전, 동태해물찜, 훈제 연어 스크램블, 저지방 생선 스튜 외 50개 정도의 카테고리가 더 있어요
[샐러드 영상 카테고리]
닭가슴살, 토마토, 스팀드, 그릴 수박, 딸기, 배, 봄동 시저, 국수호박, 파스타, 브로콜리, 한라봉, 시금치, 치즈 사과, 치아시드감자, 감자, 구운 라디치오, 레몬드레싱 수박, 검은깨 드레싱의 연근, 나초망고, 구운 여름 옥수수, 문어 참나물, 사과 호두, 메이플, 애호박 새우, 모둠 콩, 퀴노아, 가을, 토마토 오디, 렌틸콩 과일, 오징어, 파파야, 더덕, 두부, 케이준 치킨, 파프리카 망고, 그릴 천도복숭아 외 50개 정도의 추가카테고리가 있어요
[디저트 영상 카테고리]
파베 초콜릿, 찰떡아이스, 배추굴카나페, 마카롱, 팝초콜릿, 초콜릿푸딩, 브라우니 디저트, 당근머핀, 새우 카나페, 파베 생초콜릿, 넛트초콜릿, 리얼 브라우니, 채소크래커, 초코 과일퐁듀, 캐러맬 견과류 카나페, 쉘 초콜릿, 오이 카나페, 초코치즈타르트, 귤 머핀, 크런치몰드초콜릿, 코코아마들렌, 망고아이스바, 밀크 라이스 푸딩, 천도복숭아 타르트, 와인초콜릿, 버터플라이 새우, 고프르, 포도치즈타르트, 트러플 초콜릿, 오렌지타르트, 라즈베리 아이스바, 에그 타르트, 검은콩 브라우니, 마들렌, 홍시 아이스크림, 커피콩 초콜릿 외 많은 추가 카테고리가 있어요
[제과/제빵 레시피 카테고리]
크림치즈쿠키, 케이크, 고구마피자, 단감 찹쌀케이크, 에클레어, 생크림케이크, 포테이토 키쉬, 딸기 롤케이크, 딸기생크림케이크, 생우유 롤케이크, 딸기치즈 타르트, 당근케이크, 갸또 오 쇼콜라, 메이플스콘, 티라미수, 브라우니, 시나몬롤쿠키, 투톤 로즈쿠키, 버터쿠키, 옥수수 스콘 등 이외의 제과관련 추가 정보들이 있어요
[그릴-불고기 레시피 카테고리]
불고기 레시피, 바싹 불고기, 파불고기, 불고기 양념, 뚝배기 불고기, 닭안심 불고기, 채소 불고기, 뚝배기 버섯 불고기, 모둠 버섯 불고기, 닭불고기, 배추 불고기 볶음 이외의 다수의 관련 영상 정보들이 있어요
=====

스크린샷



요리레시피 동영상 목록

영상에 대한 카테고리들이 있어요


영상에 대한 대분류 카테고리 정보들이 있어요



요리레시피 영상을 클릭한 경우 유투브의 해당 영상이 있는 페이지가 호출되었어요

=====

방문해 주심에 감사드려요~
즐거운 시간 보내세요~



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
...


즐거운 시간 보내세요~