안드로이드에서 final 을 자주 쓰는이유가 무엇일까요?

 

먼저 코드를 봅시다.

 

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class ButtonTestActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button btn = (Button) findViewById(R.id.Button01);

btn.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
btn.setText("clicked!");
}
});
}
}

 

여기서 final 을 쓴 이유가 무엇일까요?

저기서 final 을 쓰지 않으면 아래와 같은 오류가 납니다.

 

Cannot refer to a non-final variable btn inside an inner class defined in a different method

 

사실 처음에는 “final 을 쓰면 전역변수처럼 되나?” 라고 생각했는데 그렇다면 static 하고 비교가 애매해 집니다.

그리고 메모리관리 측면에서도 낭비가 되죠.

 

여기서 final 의 일반적인 정의를 좀 알아봅시다.

바로 “상수화” 시킨다는것 입니다.

 

사실 이 말은 프리미티브 타입에만 통하는 말입니다.

프리미티브 타입이 아닌 객체에는 “참조를 변경할수 없음” 이라는 말이 더 어울립니다.

 

결국 위의 소스에서 btn 이라는 변수의 참조가 변경되지 않기 때문에 컴파일러가 변수명이 아니라 참조주소로 바로 접근 가능하도록 할 수 있게 되는것 입니다.

 

이것은 전역변수는 아니고 “지역적 치환문” 정도로 생각하는게 좋을꺼 같습니다.

by cranix 2010.12.23 18:32

이번에는 AuthenticationService 를 실제로 구현해 보도록 하겠습니다.

 

이전에 “Accounts & Sync” 메뉴에 내 계정을 등록시키는 작업을 했습니다.

그 다음에 원하는 것은 내가 만든 계정을 클릭했을 때 로그인 창을 띄우는 것 입니다.

 

그런데 여기서 문제는 실제로 로그인 을 요청하는 부분은 다른 Process 가 한다는 것이죠.

결국 이 프로세스가 우리가 만든 Service 와 통신하기 위해서는 바인더를 이용하여야 합니다.

 

안드로이드에서는 이를 위해서 AbstractAccountAuthenticator 라는 추상 클래스를 제공합니다.

우리는 이를 구현해서 iBinder 만 넘겨주면 됩니다.

 

이를 소스로 살펴보면 아래와 같습니다.

 

package net.cranix.android.cranixsyncsample.authenticator;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class AuthenticationService extends Service {
private Authenticator authenticator;

@Override
public void onCreate() {
authenticator = new Authenticator(this);
}

@Override
public IBinder onBind(Intent intent) {
return authenticator.getIBinder();
}
}



 

즉 Authenticator 는 AbstractAccountAuthenticator 를 구현한 클래스이고 이것을 우리가 만든 서비스에서 만들고 사용하는 모습입니다.

 

이제 로그인 및 기타 처리는 Authenticator 클래스에서 구현해주면 됩니다.

Authenticator 클래스는 아래와 같습니다.

 

package net.cranix.android.cranixsyncsample.authenticator;

import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.NetworkErrorException;
import android.content.Context;
import android.os.Bundle;


public class Authenticator extends AbstractAccountAuthenticator {

public Authenticator(Context context) {
super(context);
// TODO Auto-generated constructor stub
}

@Override
public Bundle addAccount(AccountAuthenticatorResponse response,
String accountType, String authTokenType,
String[] requiredFeatures, Bundle options)
throws NetworkErrorException {
// TODO Auto-generated method stub
return null;
}

@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response,
Account account, Bundle options) throws NetworkErrorException {
// TODO Auto-generated method stub
return null;
}

@Override
public Bundle editProperties(AccountAuthenticatorResponse response,
String accountType) {
// TODO Auto-generated method stub
return null;
}

@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle options)
throws NetworkErrorException {
// TODO Auto-generated method stub
return null;
}

@Override
public String getAuthTokenLabel(String authTokenType) {
// TODO Auto-generated method stub
return null;
}

@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response,
Account account, String[] features) throws NetworkErrorException {
// TODO Auto-generated method stub
return null;
}

@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle options)
throws NetworkErrorException {
// TODO Auto-generated method stub
return null;
}

}



 

AbstractAccountAuthenticator 를 상속받은 Authenticator 클래스의 기본형은 위와 같습니다.

이제 각각의 메소드들은 시스템에서 계정관련 작업시 알아서 호출하게 됩니다.

 

여기서는 간단하게 계정추가를 만들어보도록 하겠습니다.

계정추가는 설정에 “Accounts & Sync” 에서 계정을 누를때 일어나며, 위의 메소드 중에서는 “addAccount” 를 호출하게 됩니다.

 

그럼 위 소스를 아래와 같이 수정합니다.

 

public class Authenticator extends AbstractAccountAuthenticator { 
private Context context;
public Authenticator(Context context) {
super(context);
this.context = context;
}
@Override
public Bundle addAccount(AccountAuthenticatorResponse response,
String accountType, String authTokenType,
String[] requiredFeatures, Bundle options)
throws NetworkErrorException {

AccountManager manager = AccountManager.get(context);

Account account = new Account("cranix",accountType);
manager.addAccountExplicitly(account, "passowrd", null);
return new Bundle();
}




}

 

여기서는 AccountManager.addAccountExplicitly 를 사용하여 계정을 추가하는데 이것을 사용하려면 권한이 필요합니다.

아래내용을 manifest 파일에 추가합니다.

 

<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"></uses-permission>

 

이제 설정 메뉴의 “Accounts & Sync” 에서 “Add account” 를 누른후에 자신이 추가한 계정을 클릭하면 아래와 같이 추가되는것을 볼 수 있습니다.

image

 

이번 포스트에서는 UI 없이 간단하게 추가되도록 만들었습니다.

안드로이드에서는 여기서 사용하는 UI 를 지원하기 위해서 AccountAuthenticatorActivity 라는 클래스를 제공합니다.

 

다음 에는 이 클래스를 이용해서 UI 를 붙혀서 로그인 하는법을 알아보도록 하겠습니다.

by cranix 2010.12.23 17:21

안드로이드에서 ID/PW 는 어떻게 저장할까요?

어플리케이션 별로 알아서 저장해도 상관은 없지요.

 

그러나 안드로이드에서는 이러한 로그인 정보를 통합적으로 관리 할 수 있도록 Authenticator Service 를 제공합니다.

안드로이드의 설정에 “Accounts & Sync” 메뉴에 가보면 이렇게 관리되는 계정을 확인 할 수 있습니다.

 

아마 대부분 Google 계정만 등록되어 있을텐데 이번 포스트에서는 내가 만든 Authenticator Service 를 등록해 보도록 하겠습니다.

 

 

먼저 설정의 “Accounts & Sync” 메뉴의 계정리스트에 나오도록 해야하는데 이것은 서비스 구현으로 이루어 집니다.

 

1. manifest 에 서비스 등록하기

   - AndroidManifest.xml 파일에 다음과 같이 서비스를 등록합니다.

<service android:name=".authenticator.AuthenticationService"> 
<intent-filter>
<action
android:name="android.accounts.AccountAuthenticator"
/>
</intent-filter>
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator"
/>
</service>


 

2. xml 리소스 등록하기

   - xml/authenticator.xml 파일을 만들고 아래 내용을 입력합니다.

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


<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="net.cranix.android.cranixsyncsample"
android:icon="@drawable/icon"
android:smallIcon="@drawable/icon"
android:label="@string/app_name"
/>


 

3. sample 서비스 만들기

   - 일단 등록이 되는지 확인을 위해 아래와같이 빈 Service 를 만듭니다.

package net.cranix.android.cranixsyncsample.authenticator;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class AuthenticationService extends Service {
@Override
public void onCreate() {
// TODO Auto-generated method stub
}

@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}

}


 

   - 그후 설정에 “Accounts & Sync” 에 가보면 등록이 되어 있는것을 볼 수 있습니다.

image

 

 

자신이 추가한 계정을 클릭하면 아무 반응이 없는것을 알 수 있습니다.

서비스를 구현하지 않았으니 당연한 결과 입니다.

 

3번에서 만든 서비스를 구현해서 로그인 정보 기록이나 나아가서 주소록 싱크 어플 등을 만들수 있게 됩니다.

다음에는 이 서비스를 실제로 구현하는 방법을 알아보도록 하겠습니다.

by cranix 2010.12.23 14:53

안드로이드 sync 를 사용하기 위해서는 계정접근을 위한 Service 와 sync 를 위한 Service 가 필요합니다.

 

 

1. 계정 접근을 위한 Service

   - 아래와 같은 형태로 Service 를 추가하게 됩니다.

<service
    android:name=".authenticator.AuthenticationService"
    android:exported="true">
    <intent-filter>
        <action
            android:name="android.accounts.AccountAuthenticator" />
    </intent-filter>
    <meta-data
        android:name="android.accounts.AccountAuthenticator"
        android:resource="@xml/authenticator" />
</service>

 

   - 위와 같은 형태로 서비스를 등록하면 안드로이드 설정메뉴중 “Accounts & Sync” 메뉴에 자동으로 등록됩니다.image

 

   - 여기 나오는 메뉴의 형태는 @xml/authenticator 에서 정의합니다.

<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="com.example.android.samplesync"
    android:icon="@drawable/icon"
    android:smallIcon="@drawable/icon"
    android:label="@string/label"
/>

 

  - 로그인후 받은 토큰을 내부에 저장하고 다음번 로그인시에 그 토큰으로 자동으로 로그인합니다.

 

 

 

2. Sync 를 위한 Service

  - 아래와 같은 형태로 Service 를 추가하게 됩니다.

<service
    android:name=".syncadapter.SyncService"
    android:exported="true">
    <intent-filter>
        <action
            android:name="android.content.SyncAdapter" />
    </intent-filter>
    <meta-data
        android:name="android.content.SyncAdapter"
        android:resource="@xml/syncadapter" />
    <meta-data
        android:name="android.provider.CONTACTS_STRUCTURE"
        android:resource="@xml/contacts" />
</service>

 

   - 싱크가 실행될때 위의 서비스가 자동으로 호출되게 됩니다.

   - 싱크는 저장된 토큰으로 외부와 통신해서 업데이트된 데이터를 받아와서 내부에 맞게 가공해서 업데이트 하도록 합니다.

by cranix 2010.12.20 11:39

 

contacts-2.png

 

- Contact

   - 현재 계정의 상태

   - 표시되는 이름

   - 전화번호를 가지고 있는지 유무

 

- RawContact

   - 계정 (ex-google,daum,naver,custom …)

 

- Data

   - 이름, 전화번호, Email, …

by cranix 2010.12.20 11:21
CranixDialer (v1.6)


이번 버젼에서는 다음과 같은 기능이 추가/변경 되었습니다.

  • 많은수의 연락처를 검색해도 실행속도가 느려지지 않게 수정

  • 전화번호의 형식도 나오도록 수정 (H.P, 집, 직장)

  • 부재중 통화를 클릭했을때 CranixDialer 뜨던거 삭제

  • 키패드 모드에 "전화걸기" 버튼 추가


이번 버젼에서는 많은수의 연락처를 검색해도 초기 실행속도가 느려지지 않도록 속도를 개선하는데 초점을 맞추었습니다. 사실 테스트는 안해봤는데 이제는 어느정도 속도를 보장할 수 있을듯 합니다.

그리고 부재중 통화 알람메시지를 없애보려고 찾아봤는데 다른 어플에서 띄운거라 결국 안되더군요.
그래서 아예 CranixDialer 를 클릭했을때 안뜨도록 해놨습니다.

그리고 중요한건 이번버젼부터는 베타딱지를 뗀다는 겁니다.
어느정도 안정화 단계에 접어들었고 2.2 에서 돌려봐도 제대로 돌아가더군요.

베타를 떼고서는 유료로 전환합니다.
현재 한국에서 결재가 가능한 T-Store 에 올라갈 예정입니다.
구글마켓에도 올리려고 했으나 유료로 판매하려면 다른 설정을 해야하더군요..
이부분은 더 알아보고 올리도록 하겠습니다.



by cranix 2010.07.18 17:06

CranixDialer Beta (v1.5)
이번 버젼에서는 다음과 같은 기능이 추가/변경 되었습니다.
  • 메인 리스트에 바로 전화걸기 버튼 추가
  • 버튼사운드 하나로 줄임(로딩속도 향상)
  • 메인 검색루틴 수정
  • 아이콘 변경

이번 버젼에서는 전화걸기 버튼 추가와 이전 버젼에서의 버그를 수정하였습니다.
이전 버젼에서 숫자마다 따로 사운드를 넣다보니 로딩속도 때문에 초기 구동속도가 느렸습니다.
그래서 부득이 버튼 사운드를 하나로 줄여서 구동속도를 빠르게 하였습니다.
또한 메인의 프로그램실행시 아이콘을 변경하였습니다.

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



CranixDialer Beta (v1.4)
이번 버젼에서는 다음과 같은 기능이 추가/변경 되었습니다.
  • 메인 검색 알고리즘 수정(약간의 속도향상및 몇몇 폰에서 오류나는 현상 수정예상-_-;)
  • 버튼 사운드 출력 방식 수정(기존의 딜레이 있던 현상 수정)
  • 메시지 보내는 방식 수정(몇몇 폰에서 메시지 보내기 누를때 오류나는 버그 수정 예상)

이번 버젼에서는 안정화 시키려고 노력했습니다.
사실 제가 폰이 디자이어밖에 없는 관계로 다른폰에서 테스트는 못해보았지만..ㅜㅜ
여러 예상되는 오류를 수정하였습니다.




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

CranixDialer Beta (v1.3)
이번 버젼에서는 다음과 같은 기능이 추가/변경 되었습니다.
  • 아이콘 수정
  • 새로운 연락처 추가시 업데이트 제대로 안되던 버그 수정
  • 영어 대소문자 모두 검색
  • 단축번호누를시 반응 설정
  • 버튼 누를시 사운드 효과 추가

 



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



CranixDialer Beta (v1.2)
이번 버젼에서는 다음과 같은 기능이 추가/변경 되었습니다.
  • 아이콘 변경
  • 단축번호 기능 추가
  • 짧은클릭을 "연락처보기" 로 설정해 놨을때 연락처에 없는 번호 클릭하면 오류나던거 수정
이번 버젼은 단축번호 기능을 추가하였습니다.
단축번호를 사용하기 위해서는 숫자 다이얼 패드에서 숫자를 길게 누르면 됩니다.

이후업데이트는 기능추가보다는 버그개선 및 안정화 그리고 속도개선 같은 기본적인 기능 업그레이드 될 예정입니다.


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

CranixDialer Beta (v1.1)
이번 버젼에서는 다음과 같은 기능이 추가/변경 되었습니다.
  • Setting 페이지 추가
  • 키패드,숫자패드 선택가능
  • 키패드 진동 선택가능
  • 통화및 메시지 보낸후 자동종료 선택가능
  • 짧은터치시 반응 선택가능
  • "*" 길게 누르면 진동모드/정상모드 전환
  • 전화목록이 없을때 실행안되던 버그수정
  • 아이콘 변경 (미반영)
  • 반응속도 대폭 개선
  • 특정 상황에서 오류나는 버그 수정
  • "010" 을 입력하면 010 으로 시작되는 전화번호 검색되지 않음

이번 버젼은 Setting 페이지를 추가한것이 가장 큰 특징입니다.
그리고 자잘한 버그들을 수정하였습니다.

이번 버젼에서는 드디어!
안드로이드 마켓에 등록하였습니다.
마켓에서 CranixDialer 로 검색하신후에 받으시면 됩니다!


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

CranixDialer Beta (v1.0)
업데이트 목록입니다.

  • 쌍자음 검색추가
  • 클립보드 복사메뉴 추가
  • 리스트에서 back 누를시 프로그램 종료
  • 업데이트 제대로 안되던 버그 수정
  • 연락처가 통화로그와 섞이는 버그 수정
  • 다이얼 버튼 추가 !
  • 속도개선
  • 부재중 통화왔을때 CranixDialer 누르면 알람메시지 사라지도록 수정 (미구현)

이번 버젼은 다이얼버튼을 추가했습니다.
위에서 보는바와같이 초성과 숫자가 한꺼번에 검색됩니다.

부재중 알람메시지 사라지게 하는방법을 아직 찾지 못했네요.-_-;
혹시 아시는분 있으면 가르쳐 주시기 바랍니다.


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

CranixDialer Beta (v0.9)
  • 아이콘 변경
  • 알림메시지의 부재중 통화 클릭하면 CranixDialer 도 선택에 뜨도록 수정
  • 시간이 스크롤바에 가려지지않게 수정
  • 최근 통화목록과 연락처가 통합되어 한꺼번에 검색됨
  • 기본으로 최근통화목록이 제일위에 정렬되고 검색시에는 검색어 우선순위별로 자동정렬됨
  • 리스트를 터치하면 키보드가 숨겨져서 넓은 화면이 되도록 수정
  • 검색텍스트박스를 위로 올림
  • neoStyle 키보드를 사용시 맨윗사람 안보이는 버그 수정
  • 프로그램 정보 창 추가
  • *119 와 같은 형태의 전화 전화걸기가능
  • 소스코드 재작성
  • 돋보기 버튼 길게 클릭하면 CranixDialer 뜨게 수정

제 폰에서 마루타 실험한 결과 버그를 확인하지 못했습니다.
그래서 이렇게 올립니다.
테스트 부탁드립니다.





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



CranixDialer Beta (v0.81)

통화목록의 날짜 버그때문에 급히 수정버젼을 올립니다.
이번 버젼에서 추가/수정 된 기능은 아래와 같습니다.

  • 여러개 한꺼번에 나오는 송수신목록 하나로 합치고 갯수만 표시하도록 수정
  • 송/수신/부재중 통화 화살표 아이콘으로 표시
  • 각 송수신목록별 통화로그 출력


※ 0.8 버젼에 시간 오늘/내일 표시하는 부분과 송수신 갯수 출력하는 부분이 버그가 있어서 수정해서 올립니다.


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




CranixDialer Beta (v0.7)
이번 버젼에는 다음과 같은 기능이 추가되었습니다.
  • 검색어 우선순위 (첫글자부터 매칭된 이름이나 붙어있는 이름 우선순위줌)
  • 클릭시 바로 전화걸리지 않고 선택메뉴 나옴
  • 모르는 번호는 Unknown 대신 전화번호로 나오기
  • 통화기록 개별삭제 및 전체삭제
  • 기타 자잘한 버그수정
  • 메시지 보내기 메뉴 추가
이번 버젼에서 UI 추가나 수정은 없습니다.
대신 검색기능을 조금 더 강화하고 편의기능을 추가하였습니다.

다음버젼에는 UI 의 전체적인 수정이 있을 예정입니다.
"초성검색 다이얼 버튼" 역시 UI 부분이기 때문에 다음버젼에 추가될 예정입니다.

더 추가할 기능이나 아이디어 있으시면 댓글 달아주세요.
적극 반영하겠습니다.


--------------------------------------------------------------------------------------
CranixDialer Beta (v 0.5)





안드로이드 초성검색 어플 CranixDialer!
초성검색 기능에 충실하게 만들었습니다.

아직 베타라 수정사항이 많이 있을것을 예상됩니다.
써 보시고 버그나 수정사항이 있으시면 댓글 달아주세요.
다음 버전에 반영하도록 하겠습니다.








by cranix 2010.06.10 23:07
안드로이드에서 UBI FS 를 사용하기 위해서는 아래와 같이 커넬셋팅을 해야한다.
먼저 make menuconfig 로 들어간 다음에 아래 순서대로 빌트인 (*) 을 하자
참고로 커널버젼 2.6.29 이다.


- Device Drivers -> Memory Technology Device (MTD) support -> UBI - Unsorted block images -> Enable UBI <*>

- File systems -> Miscellaneous filesystems -> UBIFS file system surpport <*>


 
by cranix 2010.05.27 15:47
개요
안드로이드 기본 소스코드는 밧데리가 없으면 시작되자마자 바로 꺼지도록 되어있다.
그래서 타겟보드에서 작업할 때에는 가장 먼저 이 밧데리 부분을 주석걸어 주어야지 꺼지지않고 실행이 된다.
이번 포스트에서는 그 방법을 알아보도록 하자.


밧데리 패치
"frameworks/base/services/java/com/android/server/BatteryService.java" 파일을 열어자.

     private final void shutdownIfNoPower() {

        // shut down gracefully if our battery is critically low and we are not powered.

        // wait until the system has booted before attempting to display the shutdown dialog.

        /*

        if (mBatteryLevel == 0 && !isPowered() && ActivityManagerNative.isSystemReady()) {

            Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);

            intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);

            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            mContext.startActivity(intent);

        }

        */

    }


    private native void native_update();


    private synchronized final void update() {

        //native_update();


        boolean logOutlier = false;

        long dischargeDuration = 0;

        ...
약 186 라인쯤에 위와 같은 부분을 찾을 수 있는데 위처럼 주석을 걸어주자.
이제 컴파일하고 타겟보드에 올리고 실행하면 제대로 될 것이다.
by cranix 2010.03.30 12:50
들어가며
안드로이드 소스를 분석하다보면 시스템쪽의 java 소스를 봐야할 경우가 많은데 이클립스상에서 따라내려갈 수 없게 되어있어서 불편할때가 많았다.
안드로이드 sdk 에다가 이클립스 소스를 연결하는법을 알아보도록 하자.


SDK 에 안드로이드 소스 링크걸기
이클립스에서는 기본적으로 jar 파일에다가 소스 링크걸기를 지원한다.
그런데 안드로이드의 jar 파일은 이 기능이 꺼져있어서 임의로 링크 걸수없게 되있다.
그러나 이클립스에서 안드로이드 프로젝트를 만들어서 android.jar 파일의 Source attachment 부분을 보면 기본적으로 경로가 잡혀있음을 알 수 있다.
결국 해당 경로에 sources 디렉토리를 만들어서 소스를 넣어주면 링크가 된다는 소리다.
그러기 위해서는 소스를 먼저 다운받아야 하는데 아래 글을 참조해서 다운 받기로 하자.
android 소스 다운로드 받기 
그다음 sdk 를 설치한 경로의 platform/android-7 디렉토리에 다가 심볼릭 링크를 걸어주면 된다.

# ln -s eclare_src/ android-sdk-linux_86/platforms/android-7/sources

이클립스가 켜져있다면 F5 를 눌러서 리플래쉬 해 주면 소스를 로딩하는것을 볼 수있다.
이제 원하는 소스를 마음대로 볼 수 있다.

by cranix 2010.03.22 00:37
| 1 2 3 4 |