본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[android] authenticator 관련 Tutorial

by 돼지왕 왕돼지 2015. 12. 5.
반응형


 [android] authenticator 관련 Tutorial


참조 : http://cranix.net/346

http://cranix.net/347
http://cranix.net/349
http://cranix.net/350


AbstractAccountAuthenticator, AbstractThreadedSyncAdapter, account, account-authenticator, AccountAuthenticatorActivity, AccountAuthenticatorResponse, AccountManager, accounts, accounts & sync, accounttype, Action, addAccount, addAccountExplicitly, Android, android.accounts.accountauthenticator, android.permission.AUTHENTICATE_ACCOUNTS, android.permission.READ_SYNC_SETTINGS, android.permission.WRITE_SYNC_SETTINGS, android:accountType, android:contentAuthority, android:supportsUploading, authenticator, authenticator service, auto sync, Bundle, confirmCredentials, ContentProviderClient, editProperties, getAuthToken, getAuthTokenLabel, getIBinder, getSyncAdapterBinder, hasFeatures, ibinder, Icon, intent-filter, KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, KEY_ACCOUNT_NAME, KEY_ACCOUNT_TYPE, KEY_INTENT, Label, manifest, meta-data, networkexception, onBind, override, Resource, Service, setAccountAuthenticatorResult, smallicon, Sync, sync-adapter, syncadapter, System, tutorial, updateCredentials, uses-permission, [android] authenticator 관련 Tutorial, 계정, 구글 싱크


Authenticator Service

-
안드로이드 설정의 Accounts & Sync 메뉴의 기능 제공을 위해서 필요하다.



-
@ Manifest

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


-

@ xml/authenticator.xml

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" 
    android:accountType="com.test.test" 
    android:icon="@drawable/icon" 
    android:smallIcon="@drawable/icon" 
    android:label="@string/app_name" 
    />


-

@AuthenticationService.java

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 목록에 등록이 된다.



-
AuthenticationService 만 만든다고 만사 오케이는 아니다.
계정에 대한 어떤 Action 을 취할 때 할 행동을 정의해줘야 하는데, 이는 Authenticator 를 통해서 이루어진다.



-

@AuthenticationService.java

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

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; 






-

위의 override 함수들은 계정에 어떤 action 을 취했을 떄 system 에서 호출되는 함수들이다.
계정 및 동기화 ( Accounts & Sync ) 에서 예를 들어 계정추가가 가능하도록 하려면 addAccount 를 구현해주면 된다.



-

@Manifest

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



-

@ Authenticator.java

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 {
        
        Account account = new Account("test",accountType); 
        AccountManager manager = AccountManager.get(context); 
        manager.addAccountExplicitly(account, "mypassword", null); 
        return new Bundle(); 
    }
...
}



-

계정 추가는 permission 이 필요하기에 permission 을 주고, 그 다음 계정 추가 코드를 추가해주면 된다.



-
AccountAuthenticatorActivity 를 통해 UI 도 제공하기.

@ Authenticator.java

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 {
        Intent intent = new Intent(context,AuthenticatorActivity.class);
        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);

        final Bundle bundle = new Bundle();
        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
        return bundle;
    }

...
}



-

@ AuthenticatorActivity.java

public class AuthenticatorActivity extends AccountAuthenticatorActivity {

    private EditText textId;
    private EditText textPassword;

    private AccountManager accountManager;

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);

        final Button btnLogin = (Button) findViewById(R.id.Button_login);
        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doLogin();
            }
        });

        final Button btnCancel = (Button) findViewById(R.id.Button_cancel);
        btnCancel.setOnClickListener(new View.OnClickListener() { 
            @Override
            public void onClick(View v) {
                doCancel();
            }
        });

        textId = (EditText) findViewById(R.id.EditText_id);
        textPassword = (EditText) findViewById(R.id.EditText_password);
        accountManager = AccountManager.get(this);
    }

    private void doLogin() {
        final String id = textId.getText().toString();
        final String password = textPassword.getText().toString();
        final Account account = new Account(id,Constants.ACCOUNT_TYPE); 
        if (accountManager.addAccountExplicitly(account, password, null)) {
            final Intent intent = new Intent();
            intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, id);
            intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
            setAccountAuthenticatorResult(intent.getExtras()); // 핵심
            setResult(RESULT_OK,intent);
            finish();
        } else {
            doCancel();
        }
    }

    private void doCancel() {
        setResult(RESULT_CANCELED);
        finish();
    }
}



-

Activity 를 띄울 때 intent extra 로 AccountAuthenticatorResponse 객체를 담고 있어야 한다.
결과는 setAccountAuthenticatorResult( Bundle ) 을 통해 전달해야 한다.

기존 addAccount 에서 AuthenticatorActivity 로 처리를 위임한 것이다.







SyncAdapter 를 통해 Auto Sync 하게 하기.


SyncAdapter 는 구글 싱크가 일어날 때 자동으로 함께 Sync 처리해주는 부분이다.
SyncAdapter 는 예상했듯이 Service 로 이루어져 있다.


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



@ xml/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="com.test.test"
    android:supportsUploading="false"
    />


android:contentAuthority 는 sync 할 ContentProvider 를 지정한다.
android:supportsUploading false 는 서버로 uploading 은 하지 않고 downloading 만 되는 server 가 read only 의 형태가 된다.



-

@ SyncService.java

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



-

@ SyncAdapter.java

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 처리
    }
}






반응형

댓글