레이블이 안드로이드개발팁인 게시물을 표시합니다. 모든 게시물 표시
레이블이 안드로이드개발팁인 게시물을 표시합니다. 모든 게시물 표시

2017년 10월 27일 금요일

안드로이드 Intent ACTION_VIEW 외부 크롬 브라우저 호출


안드로이드 Intent ACTION_VIEW 외부 크롬 브라우저 호출


String parmUnit = aplMy.getSContactDomain();
parmUnit = parmUnit + "mobile_svc/android/board/b_modify.php";
parmUnit = parmUnit + "?board_number="+sMltUrl[1]+"&login_id="+sMltUrl[2]+"&login_seq="+sMltUrl[3]+"&seq="+sMltUrl[4];

callChromeBrowser(parmUnit);

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

//외부브라우저인 크롬 브라우저 호출
public void callChromeBrowser(String url){   
//Chrome Browser Package name
String packageName = "com.android.chrome";                   

Intent i = new Intent(Intent.ACTION_VIEW);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setPackage(packageName);
i.setData(Uri.parse(url));

//Chrome Browser가 설치되어있으면 Call, 없으면 마켓으로 Install               
List<ResolveInfo> activitiesList = getPackageManager().queryIntentActivities(i, -1);
if(activitiesList.size() > 0) {
startActivity(i);
} else {
Intent playStoreIntent = new Intent(Intent.ACTION_VIEW);
playStoreIntent.setData(Uri.parse("market://details?id="+packageName));
playStoreIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(playStoreIntent);
}
}

ACTION_VIEW만 하면 브라우저 목록들이 뜨는데, 크롬브라우저 지정하면 크롬브라우저가 호출이 되어 호출하는 단계가 줄어들어 더 편리해져요

크롬브라우저가 없으면 설치하러 플레이스토어를 통하여 설치하러 이동하고, 있으면 크롬 브라우저를 호출한다

Have a nice day~


2017년 9월 3일 일요일

안드로이드 서포트 라이브러리 android support library 다운로드 정보


안드로이드 서포트 라이브러리 android support library 다운로드 정보



http://androidtoolsofflinedownload.blogspot.kr/p/download-android-support-library-offline.html



2017년 8월 10일 목요일

안드로이드 키보드 바로 올라오게 하기, 키보드 올리기, 내리기


안드로이드 키보드 바로 올라오게 하기, 키보드 올리기, 내리기

샘플)
//키보드 올리기
dlgCategoryAdd.etCategoryEnterName.requestFocus();
InputMethodManager imm = (InputMethodManager)actMain.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(imm.SHOW_FORCED, imm.HIDE_IMPLICIT_ONLY);

//키보드 내리기
InputMethodManager imm = (InputMethodManager)actMain.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(imm.HIDE_IMPLICIT_ONLY, 0);

have a nice day~



2017년 5월 22일 월요일

안드로이드 한국에 자동차 노선 그리기 구현 T Map의 api 이용

안드로이드 한국에 자동차 노선 그리기 구현 T Map의 api 이용

T map 개발자 사이트 들어가시면 api가 있어요

1) 가입
2) 로그인
3) 인증키 생성

*) 자바로  개발

자동차 노선과 거리 산출

즐거운 시간  보내세요~


2017년 5월 18일 목요일

안드로이드 ListView 초기화 및 갱신(refresh), notifyDataSetChanged


안드로이드 ListView 초기화 및 갱신(refresh)

소스_이미지로 보기)


소스_텍스트로 보기)

//리스트뷰의 목록을 셋팅해준다
if(adapter==null){
adapter = new FolderListAdapter(getContext(), R.id.lvSubCompany, arCompanyList);
lvSubCompany.setAdapter(adapter);
lvSubCompany.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
;
}

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if ((firstVisibleItem + visibleItemCount) == totalItemCount) {
Log.v(TAG, "IN, totalItemCount = " + totalItemCount);

if(arFMList==null)return;

//결과를 다 출력했으면 더 출력하지 않는다
if(iResultEnd == arFMList.size())return;

//시작점 계산
if((iResultStart+5)>=arFMList.size()){
iResultStart = arFMList.size();
}else{
if(iResultStart==-5){
iResultStart = 0;
}else{
iResultStart = iResultEnd;
}
}

//끝점 계산
if((iResultEnd+5)>=arFMList.size()){
iResultEnd = arFMList.size();
}else{
iResultEnd = iResultEnd + 5;
}

//결과를 출력해준다
outputResult();
}
}
});
} //end adapter
else{
adapter.notifyDataSetChanged();    
}


2017년 3월 2일 목요일

안드로이드에서의 클립보드 구현 ,android clipboard


안드로이드에서의 클립보드 구현 ,android clipboard 


java source )

public synchronized void clipboardProc(){

if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) actMain.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText( /*hiData.getMemoCt()*/ etDdayDetailMemo.getText().toString() );
} else {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) actMain.getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText("Copied Text",  /*hiData.getMemoCt()*/ etDdayDetailMemo.getText().toString() );
clipboard.setPrimaryClip(clip);
}

Toast.makeText(actMain, "Copied ~ ", Toast.LENGTH_LONG).show();
}

이미지로 보기 )



2017년 2월 27일 월요일

안드로이드 글 자르기 android:ellipsize와 singleLine


안드로이드 글 자르기 android:ellipsize와 singleLine

text )
<TextView
android:id="@+id/tvUnDdayName"
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="60"
android:textSize="15dip"
android:textColor="#333333"
android:singleLine="false"
android:maxLines="1"
android:ellipsize="end" 
android:layout_gravity="center_vertical|left"
android:gravity="center_vertical|left" />

image ) 



2017년 2월 24일 금요일

안드로이드 dp를 픽셀로 변환 _ dp(dip) -> pixel로 변환


안드로이드 dp를 픽셀로 변환 _ dp(dip) -> pixel로 변환


함수 ) 

/**
 * 변환Convert dp/dpi to pixel values
 * @파라미터 context need to get display metrics
 * @파라미터 dp DP value
 * @리턴값 pixel value
 */
public static int dpToPx(Context context, int dpValue) {
    float density = context.getResources().getDisplayMetrics().density;
    return Math.round((float)dpValue * density);
}



사용 예제 ) 

/*
 * 폴더추가 팝업을 띄워준다
 */
public synchronized void showCategoryAddPopup(){
Display display = ((WindowManager)actMain.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int iWidth = display.getWidth();
int iHeight= display.getHeight();
if(dlgCategoryAdd == null){
dlgCategoryAdd = new DialogCategoryAdd(actMain);
}
if(iWidth<=480){
dlgCategoryAdd.getWindow().setLayout(iWidth*9/10, dpToPx(actMain, 250) /*(iHeight*5)/10*/ ); //다이알로그의 사이즈를 조절
}else{
dlgCategoryAdd.getWindow().setLayout(iWidth*9/10, dpToPx(actMain, 250) /*(iHeight*5)/10*/ ); //다이알로그의 사이즈를 조절
}
dlgCategoryAdd.show();
}



2017년 2월 16일 목요일

안드로이드 스튜디오의 설치 [구글에서 직접 제공하는 툴]하는 방법


안드로이드 스튜디오의 설치 [구글에서 직접 제공하는 툴]하는 방법

다운로드 사이트 :
https://developer.android.com/studio/install.html

안드로이드 SDK는 3.2 기가정도
피시에 설치되어 있으면 체크사항에서 제외하고 설치하세요~
링크를 해주세요

컴파일과 실행시 에러가 나는데, Android SDK를 업데이트하거나 하니까 컴파일 빌드가 잘 된다
안 될 경우 에러메시지가 나오니 그에 맞추어서 설치하거나 설정해주시면 돼요

Component Installer를 설치하라고 나와서 설치하고 있어요
build.gradle > support-v4:19 등의 설치 오류
여러가지 설치 콤포넌트가 필요하다
여러번 Install Repository and sync project
설치  후 Finish

에러1 :
다양한 단말기에 배포하는데 있어서의 에러
values-ldltr-v21.xml의 Widget... 에러
해결방법 : 진행중


2016년 11월 27일 일요일

AlertDialog 다이알로그의 뒷 배경이 검게 변하지 않게 = 밝게 만들어주기


AlertDialog 다이알로그의 뒷 배경이 검게 변하지 않게 = 밝게 만들어주기

final HistoryItem ciUnit = hmUnit;
final CharSequence[] AllRegions = {"Modify", "Delete"};
AlertDialog.Builder alt_bld = new AlertDialog.Builder(actMain);      
alt_bld.setCancelable(true);
alt_bld.setIcon(R.drawable.icon_settings_small);
alt_bld.setTitle("Options");
alt_bld.setSingleChoiceItems(AllRegions, -1, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if(item==0){ //Modify
;
}else if(item==1){ //Delete
deleteConfirmSearch(ciUnit);
}
dialog.cancel();
dialog.dismiss();
}
});
AlertDialog alert = alt_bld.create();
alert.show();

//배경화면이 검게 변하지 않게 만들어주는 소스
alert.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);

have a nice day~


2016년 9월 22일 목요일

안드로이드 Notification.FLAG_NO_CLEAR - 사라지지 않는 알림내용


안드로이드 Notification.FLAG_NO_CLEAR - 사라지지 않는 알림내용

안드로이드 어플을 보시면 위 상단에 알림창이 있는데, 여기에 Notification 내용이 있어요
게시판의 공지사항처럼
디데이 어플에는 몇일이 남았는지 알려주는 요인들을 Notification을 활용해서 위에 띄워주면 편리해요

Notification의 편리함 : 중요한 내용을 확인하고자 할 경우에 어플을 실행해야 하는데, 단축아이콘 처럼 노티바에서 클릭해서 들어가기가 편리해요
또한 클릭해서 어플에까지 들어갈 필요없이 간단한 정보이면 상태바에서 확인하는 것으로 끝나기 때문에 편리해요

Notification의 특성 : 좌 혹은 우로 제스처하면 사라지는 Notification이 있는데, 이를 고정해놓고 제스처를 해도 사라지지 않게 하고 싶은 경우가 있는데,

사라지지 않게 하려면 다음 옵션을 지정해주면 돼요

Notification.FLAG_NO_CLEAR

notification.flags = Notification.FLAG_NO_CLEAR;


즐거운 시간 보내세요~


2016년 9월 16일 금요일

안드로이드 상태바에 알림내용 표기 (Notification Bar)


안드로이드 상태바에 알림내용 표기 (Notification Bar)

상단바에 알림을 설정하는 소스

샘플소스 _ 자바 ) 

/*
 * 상단바에 고정
 */
public synchronized void topBarSetting(){

// 알림을 띄우기 위해서 서비스를 불러온다.
NotificationManager notificationManager = (NotificationManager)actMain.getSystemService(Activity.NOTIFICATION_SERVICE);
// Set the icon, scrolling text and timestamp
// 상태바에 띄울 알림을 생성한다. drawable은 상태바에 쓰일 아이콘,
// text는 알림이 도착한 순간 상태바 전체에 나타나는 메세지,
String text = hiData.getDdayTitle();

String sUnitDateSrc = hiData.getDdayYmd();
String sUnitDate = sUnitDateSrc.substring(0, 3);
sUnitDate = sUnitDate + "-" + sUnitDateSrc.substring(3, 5);
sUnitDate = sUnitDate + "-" + sUnitDateSrc.substring(5, 7);
sUnitDate = sUnitDateSrc + " 00:00:01.0";
//timestamp 형식 : "2009-03-20 10:20:30.0";
java.sql.Timestamp t = java.sql.Timestamp.valueOf(sUnitDate);
long lTime = t.getTime();

Notification notification = new Notification(R.drawable.icon_start50, text,
lTime);

// 아래는 위에서 불러온 방식으로 알림 방식 설정을 하는 것이다 : 진동
notification.defaults = Notification.DEFAULT_VIBRATE;

// 아래 코드는 사용자가 알림을 터치했을 때 액티비티를 호출하기 위한 인텐트이다
PendingIntent contentIntent = PendingIntent.getActivity(actMain, 0,
new Intent(actMain, LauncherActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) /*FLAG_ACTIVITY_NEW_TASK, FLAG_ACTIVITY_CLEAR_TOP*/
.putExtra("noti_timestamp", hiData.getEnterTime()),
PendingIntent.FLAG_UPDATE_CURRENT);
// Set the info for the views that show in the notification panel.
// 상태바를 내렸을 때 알림 패널에 대한 설정이다
notification.setLatestEventInfo(
actMain,
hiData.getDdayTitle(),
hiData.getMemoCt(),
contentIntent);

// Send the notification.
String sUnitTagKey = hiData.getEnterTime();
int iUnitLength = hiData.getEnterTime().length();
int iUnitNotiKey = Integer.parseInt(hiData.getEnterTime().substring(iUnitLength-5, iUnitLength-1));
notificationManager.notify(sUnitTagKey, iUnitNotiKey, notification);

if(notificationManager!=null){
notificationManager = null;
}
}

/*
 * 상단바에 고정 해제
 */
public synchronized void topBarSettingRelease(){

NotificationManager notificationManager = (NotificationManager)actMain.getSystemService(Activity.NOTIFICATION_SERVICE);
String sUnitTagKey = hiData.getEnterTime();
int iUnitLength = hiData.getEnterTime().length();
int iUnitNotiKey = Integer.parseInt(hiData.getEnterTime().substring(iUnitLength-5, iUnitLength-1));
if(notificationManager!=null){
notificationManager.cancel(sUnitTagKey, iUnitNotiKey);
notificationManager = null;
}
}



샘플소스 _ 이미지 ) 




즐거운 시간 보내세요~



2016년 9월 15일 목요일

AlertDialog에서 이용하기 위하여 ArrayList를 String[]로 변환하기


AlertDialog에서 이용하기 위하여 ArrayList를 String[]로 변환하기 

샘플 ) 

ArrayList<String> arTemp = new ArrayList();
for(int i=0; i<arGugun.size(); i++){
HashMap hmUnit = (HashMap)arGugun.get(i);
String sUnitGugun = com.util.StringUtil.Nvl((String)hmUnit.get("gugun")); //
arTemp.add(sUnitGugun);
}

final String sUnitSido = etEnterRequestFormAddressSido.getText().toString();
final String[] items = arTemp.toArray(new String[arTemp.size()]);
AlertDialog.Builder alt_bld = new AlertDialog.Builder(actMain);
alt_bld.setCancelable(true);
alt_bld.setIcon(R.drawable.icon_start57);
alt_bld.setTitle("구군선택");
alt_bld.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
//actMain.alertCommonMsg(PhoneModels[item].toString());

etEnterRequestFormAddressGugun.setText(items[item].toString());
etEnterRequestFormAddress.setText(sUnitSido + " " + items[item].toString() + " ");

dialog.cancel();
}
});
AlertDialog alert = alt_bld.create();
alert.show();

샘플 _ 이미지보기 ) 




안드로이드 AlertDialog user defined ui _ 사용자가 정의한 UI를 다이알로그로 띄워줘요


안드로이드 AlertDialog user defined ui _ 사용자가 정의한 UI를 다이알로그로 띄워줘요 

정해진 포맷의 AlertDialog가 있는데, 이외에 사용자가 정한 UI를 띄우고자 하실 경우에 다음의 소스를 활용하세요~

xml )

<?xml version="1.0" encoding="utf-8"?>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="350dp"
        android:padding="3dp" >
        <TextView android:id="@+id/tvPopTitle"
            android:layout_width="fill_parent"
            android:layout_height="20dp"
            android:layout_marginLeft="5dp"
            android:layout_marginBottom="5dp"
            android:text=""
            android:textSize="15dp"
            android:layout_gravity="left|center_vertical"
            android:gravity="left|center_vertical" />
         <LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="330dp"
    android:background="#ffffff" >
    <ScrollView
   android:id="@+id/svPop"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:gravity = "top" >
   <LinearLayout
       android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
    <LinearLayout
android:layout_width="fill_parent"
android:layout_height="3px"/>
   <LinearLayout
android:id="@+id/llPopListBody"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/><!-- 여기에 목록들을 추가해준다.(addView 이용) -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="97dp"/>
</LinearLayout>
</ScrollView>

</LinearLayout>
    </LinearLayout>

자바 소스)

View viewAlert = actMain.getLayoutInflater().inflate(R.layout.pop_gugun_select, null);
TextView tvPopTitle = (TextView) viewAlert.findViewById(R.id.tvPopTitle);
tvPopTitle.setTextColor(Color.WHITE);
tvPopTitle.setText("구군 선택");
AlertDialog alert = alt.create();

Display display = ((WindowManager)actMain.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int iWidth = display.getWidth();
int iHeight= display.getHeight();

WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(alert.getWindow().getAttributes());
lp.width = iWidth*90/100;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;

alert.show();
Window window = alert.getWindow();
window.setAttributes(lp);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));


핵심 부분 )
*) R.layout.pop_gugun_select : pop_gubun_select.xml로 UI 구성
*) WindowManager , setAttributes를 통하여 팝업의 넓이와 높이 사이즈를 조절

-----


이미지로 보기)





즐거운 시간 보내세요~



2016년 9월 9일 금요일

안드로이드 sqllite에서 테이블 필드추가는 어떻게 하는가? alter table add


안드로이드 sqllite에서 테이블 필드추가는 어떻게 하는가?

구글과 네이버 검색중에 어렵다, 안된다는 글이 많았지만, 어느 날 조회해보니 된다는 글  이 있어서 해보니 안드로이드 sqllite에서 create table 후 alter table add가 되었어요

예문)
package com.joysoft.dday.history;

import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
import android.content.Context;

/**
 * @author Sean Owen
 */
final class HistoryDBHelper extends SQLiteOpenHelper {

  private static final int DB_VERSION = 9;
  private static final String DB_NAME = "angel_dday_history.db";
  static final String TABLE_NAME = "dday";

  HistoryDBHelper(Context context) {
    super(context, DB_NAME, null, DB_VERSION);
  }

  @Override
  public void onCreate(SQLiteDatabase sqLiteDatabase) {
    sqLiteDatabase.execSQL(
      "CREATE TABLE " + TABLE_NAME + " (" +
      " enter_time TEXT PRIMARY KEY, " + /* 등록 일시 (timestamp) */
      " image_name TEXT, " + /* 썸네일 이미지명 */
      " dday_title TEXT, " + /* 디데이 타이틀 */
      " dday_ymd TEXT, " + /* 디데이 년월일 (2016/07/10)*/
      " dday_method TEXT, " + /* 디데이 계산방법 */
 " memo_ct TEXT, " + /* 간단메모 내용 */
 " addinfo1 TEXT, " + /* 즐겨찾기여부(Y, ???) */
 " addinfo2 TEXT, " + /* 등록(업데이트)일자 */
 " addinfo3 TEXT, " + /* 추가정보3 */
 " addinfo4 TEXT, " + /* 추가정보4 */
 " addinfo5 TEXT " + /* 추가정보5 */
      " );");
  }

  @Override
  public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
  int version = oldVersion;
 if (version != DB_VERSION && oldVersion<9) {
 sqLiteDatabase.execSQL("ALTER TABLE dday ADD bar_yn TEXT;");
 sqLiteDatabase.execSQL("ALTER TABLE dday ADD bar_type TEXT;");
          }
  }
}

핵심적인 부분이 버전에 대한 부분에 맞추어서 업데이트를 해주시면 돼요

create table에서 필드를 추가도 해보았지만, 에러가 나며 적용이 되지 않았는데, 필드의 추가는 alter table add의 예약어를 사용해야 적용이 된다

위의 소스를 참조하시어 개발하시면 되겠어요


즐거운 시간 보내세요~

2016년 8월 19일 금요일

안드로이드 CalendarView 와 색상 설정


안드로이드 CalendarView 와 색상 설정



구글검색어 :
안드로이드 CalendarView 색상
android CalendarView title color

참고사이트 :

http://gakari.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-CalendarView%EB%A1%9C-%EC%89%BD%EA%B2%8C-%EB%8B%AC%EB%A0%A5%EC%9D%84-%EB%A7%8C%EB%93%A4%EC%9E%90

http://m.blog.naver.com/dlfghkjung/220632851185

alert_calendar.xml 

<?xml version="1.0" encoding="utf-8"?>
<!-- 달력 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dip"
    > <!-- android:background="#3ffa7f" -->

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <CalendarView android:id="@+id/cvPop"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:focusedMonthDateColor="#3ffa7f"
            android:unfocusedMonthDateColor="#fafafa"
            />
    </LinearLayout>
</LinearLayout>

focusedMonthDateColor : 해당되는 월의 일자 색상
unfocusedMonthDateColor : 해당되지 않는 월의 일자 색상
showWeekNumber="false" 주에 좌측에 몇주차인지 보여줄지 여부
   true : 보여준다
   false : 표기하지  않는다

이 외에 여러가지 색상설정 및 기타 설정정보들이 있어요




-----

* 년월의 색상 변경

cvPop = (CalendarView)findViewById(R.id.cvPop);

try{
ViewGroup vg = (ViewGroup) cvPop.getChildAt(0);
View child = vg.getChildAt(0);
if(child instanceof TextView) {
((TextView)child).setTextColor(Color.BLACK);
}
}catch(Exception e){
;
}

-----

* 날짜 (년월일의 선택)

cvPop.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
  @Override
  public void onSelectedDayChange(CalendarView view, int year, int month, int dayOfMonth) {
 setDate(year, month+1, dayOfMonth);
  }
});


-----

* 달력에서 스크롤만 했는데도 달력이 닫혀버리거나 이벤트가 발생하는 경우의 예외처리

cvPop.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
  @Override
  public void onSelectedDayChange(CalendarView view, int year, int month, int dayOfMonth) {
 if(cvPop.getDate() != lDate){
  setDate(year, month+1, dayOfMonth);  
 }
  }
});

if(cvPop.getDate() != lDate);
달력이  로그될 때의 지정된 날짜와 다른 경우만 이벤트 처리를 해주면 돼요
달력을 닫거나, 특정  변수에 치환시켜주는 이벤트가 발생할 시의 작업을 하시면 돼요

즐거운 시간 보내세요~




2016년 5월 6일 금요일

안드로이드개발#Vertical SeekBar



안드로이드개발#Vertical SeekBar



안드로이드 개발에 있어서 SeekBar가 있어요
수평SeekBar가 있는데, 이를 커스터마이징해서 Vertical SeekBar를 만들수가 있어요

화면을 보세요~



우측에 보이는 것이 안드로이드에 여러가지 widget이 있는데, Vertical SeekBar가 되겠어요

범주를 100으로 둘때 현재 72정도라고 Toast msg로 보여주고 있어요

---------------------------------------------------------------

UI xml)

<LinearLayout 
         android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:layout_gravity="bottom|right" 
     android:gravity="bottom|right" 
     android:paddingTop="30dip"  
     android:paddingBottom="30dip">
         <com.soft.light5.VerticalSeekBar  
             android:id="@+id/sbCapture" 
             android:layout_width="wrap_content"   
      android:layout_height="fill_parent" 
      android:max="100" 
      android:progress="0" >   
         </com.soft.light5.VerticalSeekBar> 
</LinearLayout>




java source)
VerticalSeekBar.java

package com.soft.light5;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.SeekBar;

public class VerticalSeekBar extends SeekBar {

    public VerticalSeekBar(Context context) {
        super(context);
    }

    public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public VerticalSeekBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(h, w, oldh, oldw);
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(heightMeasureSpec, widthMeasureSpec);
        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
    }

    protected void onDraw(Canvas c) {
        c.rotate(-90);
        c.translate(-getHeight(), 0);

        super.onDraw(c);
    }

    private OnSeekBarChangeListener onChangeListener;
    @Override
    public void setOnSeekBarChangeListener(OnSeekBarChangeListener onChangeListener){
        this.onChangeListener = onChangeListener;
    }

    private int lastProgress = 0;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            return false;
        }

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            onChangeListener.onStartTrackingTouch(this);
            setPressed(true);
            setSelected(true);
            break;
        case MotionEvent.ACTION_MOVE:
            super.onTouchEvent(event);
            int progress = getMax() - (int) (getMax() * event.getY() / getHeight());
             
            // Ensure progress stays within boundaries
            if(progress < 0) {progress = 0;}
            if(progress > getMax()) {progress = getMax();}
            setProgress(progress);  // Draw progress
            if(progress != lastProgress) {
                // Only enact listener if the progress has actually changed
                lastProgress = progress;
                onChangeListener.onProgressChanged(this, progress, true);
            }
             
            onSizeChanged(getWidth(), getHeight() , 0, 0);
            setPressed(true);
            setSelected(true);
            break;
        case MotionEvent.ACTION_UP:
            onChangeListener.onStopTrackingTouch(this);
            setPressed(false);
            setSelected(false);
            break;
        case MotionEvent.ACTION_CANCEL:
            super.onTouchEvent(event);
            setPressed(false);
            setSelected(false);
            break;
        }
        return true;
    }

    public synchronized void setProgressAndThumb(int progress) {
        setProgress(progress);
        onSizeChanged(getWidth(), getHeight() , 0, 0);
        if(progress != lastProgress) {
            // Only enact listener if the progress has actually changed
            lastProgress = progress;
            onChangeListener.onProgressChanged(this, progress, true);
        }
    }

    public synchronized void setMaximum(int maximum) {
        setMax(maximum);
    }

    public synchronized int getMaximum() {
        return getMax();
    }
}

-------------------------------------------------------------

사용 java)

VerticalSeekBar sbCapture = null;
...
sbCapture = (VerticalSeekBar)this.findViewById(R.id.sbCapture);
...
sbCapture.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
Toast.makeText(getApplicationContext(), 
                    " progress value : " + iLcOnOffCnt, Toast.LENGTH_SHORT).show();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override 
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
// value : progress
iLcOnOffCnt = progress;
}
});
...
sbCapture = null;
...

=====

괜찮은 요리레시피 안드로이드 어플을 소개해드려요~

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

2016년 4월 18일 월요일

안드로이드에서 두 위치간의 거리 구하기


안드로이드에서 두 위치간의 거리 구하기



배달대행 어플에 있어서 필요한 소스로, 배달기사분이 오토바이를 타고 다닐때 5초나 10초에 한번씩 위치를 전송해줘야 하는데, 이전에 전송한 위치와 현재의 위치간의 거리가 어느정도 거리가 있을 때만 서버에 업데이트를 해주는 경우 서버의 부하를 줄여줄 수가 있어요
시스템의 안정화에 기여를 하게 돼요

안드로이드에서 두 위치간의 거리 구하기로 배달대행에서 기사가 오토바이를 타고다닐 때 시스템에 기사의 위치를 전송할 때 매번 위치전송하면 서버에 부하가 있지만 어느정도 거리의 변화가 있을 경우만 전송하게 되면 서버의 부하를 줄이는 효과가 있어요

소스)

double distanceMeter;

Location locationPrev = new Location("point A");
locationPrev.setLatitude(36.12345);
locationPrev.setLongitude(105.12345);

Location locationCur = new Location("point B");
locationCur.setLatitude(35.34567);
locationCur.setLongitude(105.34567);

distanceMeter = locationCur.distanceTo(locationPrev);

소스 _ 이미지)



=====

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


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();  
     }

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

즐거운 시간 보내세요~