///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: http://cranix.net/346
안드로이드에서 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” 에 가보면 등록이 되어 있는것을 볼 수 있습니다.
자신이 추가한 계정을 클릭하면 아무 반응이 없는것을 알 수 있습니다.
서비스를 구현하지 않았으니 당연한 결과 입니다.
3번에서 만든 서비스를 구현해서 로그인 정보 기록이나 나아가서 주소록 싱크 어플 등을 만들수 있게 됩니다.
다음에는 이 서비스를 실제로 구현하는 방법을 알아보도록 하겠습니다.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: http://cranix.net/347
이번에는 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” 를 누른후에 자신이 추가한 계정을 클릭하면 아래와 같이 추가되는것을 볼 수 있습니다.
이번 포스트에서는 UI 없이 간단하게 추가되도록 만들었습니다.
안드로이드에서는 여기서 사용하는 UI 를 지원하기 위해서 AccountAuthenticatorActivity 라는 클래스를 제공합니다.
다음 에는 이 클래스를 이용해서 UI 를 붙혀서 로그인 하는법을 알아보도록 하겠습니다.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: http://cranix.net/349
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: http://cranix.net/350
이전에 Authenticator Service 를 구현해 보았습니다.
이제 이것을 이용하는 SyncAdapter 를 구현해 보도록 하겠습니다.
SyncAdapter 는 구글 싱크가 일어날때 자동으로 싱크를 처리해주는 부분으로서
“Accounts & Sync” 셋팅메뉴에서 원하는 아이디를 클릭하면 SyncAdapter 의 리스트를 확인할 수 있습니다.
그럼 먼저 “Accounts & Sync” 메뉴에서 “Add account” 버튼을 눌러 이전에 만들었던 계정으로 로그인을 합니다.
위와 같이 로그인된 아이디가 저장이 될텐데 저 아이디를 클릭하면 이 계정에 등록되어진 SyncAdapter 를 확인할 수 있습니다.
현재에는 하나도 없는것을 볼 수 있는데 이번 포스트에서 여기에 추가해보도록 하겠습니다.
SyncAdapter 는 Service 로 이루어져 있습니다.
Service 를 추가하기전에 SyncAdapter 를 쓰기 위한 권한을 추가합니다.
아래 내용을 manifest 에 등록합니다.
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
이제 아래와 같은 형태의 서비스를 추가합니다.
<service android:name=".syncadapter.SyncService">
<intent-filter>
<action
android:name="android.content.SyncAdapter"
/>
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
그다음 syncadapter.xml 파일을 추가합니다.
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="com.android.contacts"
android:accountType="net.cranix.android.cranixsyncsample"
android:supportsUploading="false"
/>
“android:contentAuthority” 는 sync 할 ContentProvider 를 지정합니다.
여기서 Sync 이름은 우리가 직접 지정하는 것이 아니고 이 ContentProvider 의 이름을 따라가기 때문에 유의해야 합니다.
“android:supportsUploading” 은 폰에서 이 SyncAdapter 의 데이터를 변경 가능한게 할지 말지를 결정하는 것 입니다.
이것을 false 로 하면 서버에서 싱크만 되고 폰에서는 수정이안되는 readonly 상태가 됩니다.
이제 마지막으로 SyncService 와 SyncAdapter 소스를 구현해 보도록 합니다.
먼저 SyncService 입니다.
package net.cranix.android.cranixsyncsample.syncadapter;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class SyncService extends Service {
private SyncAdapter syncAdapter;
@Override
public void onCreate() {
super.onCreate();
syncAdapter = new SyncAdapter(this,true);
}
@Override
public IBinder onBind(Intent arg0) {
return syncAdapter.getSyncAdapterBinder();
}
}
이 Service 는 SyncAdapter 에 모든 처리를 위임합니다.
SyncAdapter 를 보면 다음과 같습니다.
package net.cranix.android.cranixsyncsample.syncadapter;
import android.accounts.Account;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.Context;
import android.content.SyncResult;
import android.os.Bundle;
public class SyncAdapter extends AbstractThreadedSyncAdapter {
public SyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize);
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority,
ContentProviderClient provider, SyncResult syncResult) {
// TODO : Sync 처리
}
}
이제 “Accounts & sync” 메뉴에서 아이디를 클릭해 보면 아래와 같이 추가된 SyncAdapter 가 보일 것입니다.
이제 위의 “Sync Contacts” 를 클릭하거나 시스템에서 sync 가 발생할때 위 SyncAdapter 의 onPerformSync 메소드가 호출되게 됩니다.
결국 실제 Sync 를 처리하는 구문은 onPerformSync 메소드만 구현해주면 됩니다.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: http://softcream.tistory.com/91
이글은…
안드로이드에서 제공하는 AccountManager사용에 대해서 잘 설명된 http://cranix.net/349 내용을 따라가다가 에러가 나서, 이를 해결(?)한 내용을 정리한 글입니다. 아래의 부가설명을 제외한 나머지 내용은 원본 페이지의 내용을 참고하시기 바랍니다.
참고한 내용에 있는대로 하면 아래에서 오류가 난다.
accountManager.addAccountExplicitly(account, password, null);
문제가 된건 accout에 있는 account type이 맞지 않아서 발생한 현상.
결국 해결한(?) 방법은 계정에 대한 속성(xml 에 정의한)값중 accountType값을 account 생성시에 넘겨 주면 된다.
계정에 대한 정보가 있는 xml 파일에는 다음과 같이 되어 있다.
<account-authenticator xmlns:android="“http://schemas.android.com/apk/res/android”"
android:accounttype="“ClipAndBooks" service”=""
android:icon="“@drawable/ic_launcher”"
android:smallicon="“@drawable/ic_launcher”"
android:label="“@string/set_service_account”">
</account-authenticator>
android:accountType=“ClipAndBooks Service” 로 되어 있으니, 코드상의 Account에서는 다음과 같이 한다.
final Account account = new Account(id, “ClipAndBooks Service”);
그런데.. 매번 이렇게 쓰는건 불편할테니.. 별도의 class에다가 써 두는게 낫다. (아.. 용어가 맞지 않을 수 있다.)
실제 참고로 한 사이트에서도 별도 class로 만든것으로 보이는데, 이 부분에 대한 언급이 따로 없었다.
<Constants.java>
package com.clipandbooks.test.android_account;
public class Constants {
final static String ACCOUNT_TYPE = “ClipAndBooks Service”;
}
결국은 다음과 같이 한다.
final Account account = new Account(id, Constants.ACCOUNT_TYPE);
이후 나머지는 참고 사이트 내용과 동일하다.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'스마트기기개발관련 > 안드로이드 개발' 카테고리의 다른 글
[android] 안드로이드 android 상태바 상태, 투명, 색상 관련 (0) | 2016.07.28 |
---|---|
[android] 안드로이드 android 안드로이드/Android 최근 사용한 앱(홈키 롱클릭) 에서 제외 하기~!, 설정 버튼, 앱목록 버튼을 누르면 최근 사용한 앱 목록에 자신의 앱이 안뜨게 하는 방법 (0) | 2016.07.18 |
[android] 안드로이드 android 여러업체들의 결제 모듈 관련 (0) | 2016.07.13 |
[android] 안드로이드 android How to reset default launcher/home screen replacement? (0) | 2016.07.12 |
안드로이드 android 기본 런쳐 확인 및 런쳐 기본 설정 해제 방법 (0) | 2016.07.12 |