java एंड्रॉइड में प्रोग्रामेटिक रूप से एक कस्टम खाता कैसे जोड़ें?




android synchronization (3)

मैंने इसके लिए एक library लिखी है, जो आपको एंड्रॉइड खातों के प्रबंधन के लिए आवश्यक काम करने से मुक्त करती है, जैसे बाध्य सेवा, प्रामाणिक एक्सएमएल आदि को परिभाषित करना। इसके साथ काम करना 5 सरल चरणों में है:

चरण 1

ऐप के build.gradle के लिए निर्भरताओं में इसे जोड़ें:

compile 'com.digigene.android:account-authenticator:1.3.0'

चरण 2

Strings.xml में एक स्ट्रिंग के रूप में अपने प्रमाणीकरण खाता प्रकार को परिभाषित करें:

<string name="auth_account_type">DigiGene</string>

'DigiGene' को अपने खाते के प्रकार से बदलें। यह स्क्रीनशॉट में एंड्रॉइड खातों में दिखाई देता है।

चरण 3

उपयोगकर्ताओं को पंजीकृत करने के लिए अपना पंजीकरण लेआउट डिज़ाइन करें (उदाहरण के लिए यह छवि ):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.digigene.authenticatortest.MainActivity">

    <EditText
        android:id="@+id/account_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:hint="User Name"
        />

    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/account_name"
        android:gravity="center_horizontal"
        android:hint="Password"
        android:inputType="textPassword"
        />

    <Button
        android:id="@+id/register"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/password"
        android:text="register"
        android:onClick="startAuthentication"/>

</RelativeLayout>

और निम्न कोड के साथ MyRegistrationActivity.java कहें, एक नई कक्षा MyRegistrationActivity.java :

import com.digigene.accountauthenticator.activity.RegistrationActivity;

public class MyRegistrationActivity extends RegistrationActivity {
    private EditText accountNameEditText, passwordEditText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.registration_layout);
        accountNameEditText = (EditText) findViewById(R.id.account_name);
        passwordEditText = (EditText) findViewById(R.id.password);
    }

    public void startAuthentication(View view) {
        register(accountNameEditText.getText().toString(), passwordEditText.getText().toString(),
                null, null);
    }
}

चरण 4

here एक प्रविष्टि लेआउट बनाएं:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.digigene.authenticatortest.MainActivity">

    <EditText
        android:id="@+id/account_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:hint="User Name"
        />

    <Button
        android:id="@+id/register"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/account_name"
        android:text="Sign in"
        android:onClick="signIn"/>

    <Button
        android:id="@+id/add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/register"
        android:text="Add user"
        android:onClick="addUser"/>

</RelativeLayout>

यह लेआउट निम्न वर्ग के साथ जाता है:

import com.digigene.accountauthenticator.AuthenticatorManager;

public class MainActivity extends Activity {
    EditText accountNameEditText;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        accountNameEditText = (EditText) findViewById(R.id.account_name);
    }

    public void signIn(View view) {
        AuthenticatorManager authenticatorManager = new AuthenticatorManager(MainActivity.this,
                getString(R.string.auth_account_type), this, MyRegistrationActivity.class,
                MyInterfaceImplementation.class);
        String authTokenType = "REGULAR_USER";
        AuthenticatorManager.authenticatorManager = authenticatorManager;
        authenticatorManager.getAccessToken(accountNameEditText.getText().toString(),
                authTokenType, null);
    }

    public void addUser(View view) {
        AuthenticatorManager authenticatorManager = new AuthenticatorManager(MainActivity.this,
                getString(R.string.auth_account_type), this, MyRegistrationActivity.class,
                MyInterfaceImplementation.class);
        String authTokenType = "REGULAR_USER";
        AuthenticatorManager.authenticatorManager = authenticatorManager;
        authenticatorManager.addAccount(authTokenType, null, null);
    }
}

चरण 5

यह अंतिम चरण है जिसमें पंजीकरण और साइन-इन उद्देश्यों के लिए सर्वर से कनेक्ट करने के लिए आवश्यक विधियां और उसके बाद कार्यान्वित किया जाता है। निम्नलिखित में, वास्तविक मामले के विपरीत, लाइब्रेरी की कार्यक्षमता का प्रदर्शन करने के लिए, सर्वर कनेक्शन मजाक कर रहे हैं। आप निम्नलिखित कार्यान्वयन को अपने वास्तविक के साथ बदल सकते हैं।

import com.digigene.accountauthenticator.AbstractInterfaceImplementation;
import com.digigene.accountauthenticator.AuthenticatorManager;
import com.digigene.accountauthenticator.result.RegisterResult;
import com.digigene.accountauthenticator.result.SignInResult;
import com.digigene.accountauthenticator.result.SignUpResult;

public class MyInterfaceImplementation extends AbstractInterfaceImplementation {
    public static int accessTokenCounter = 0;
    public static int refreshTokenCounter = 0;
    public static int demoCounter = 0;
    public static int accessTokenNo = 0;
    public static int refreshTokenNo = 0;
    public final int ACCESS_TOKEN_EXPIRATION_COUNTER = 2;
    public final int REFRESH_TOKEN_EXPIRATION_COUNTER = 5;
    public final int DEMO_COUNTER = 15;

    @Override
    public String[] userAccessTypes() {
        return new String[]{"REGULAR_USER", "SUPER_USER"};
    }

    @Override
    public void doAfterSignUpIsUnsuccessful(Context context, Account account, String
            authTokenType, SignUpResult signUpResult, Bundle options) {
        Toast.makeText(context, "Sign-up was not possible due to the following:\n" + signUpResult
                .errMessage, Toast.LENGTH_LONG).show();
        AuthenticatorManager.authenticatorManager.addAccount(authTokenType, null, options);
    }

    @Override
    public void doAfterSignInIsSuccessful(Context context, Account account, String authTokenType,
                                          String authToken, SignInResult signInResult, Bundle
                                                  options) {
        demoCounter = demoCounter + 1;
        Toast.makeText(context, "User is successfully signed in: \naccessTokenNo=" +
                accessTokenNo + "\nrefreshTokenNo=" + refreshTokenNo +
                "\ndemoCounter=" + demoCounter, Toast.LENGTH_SHORT).show();
    }

    @Override
    public SignInResult signInToServer(Context context, Account account, String authTokenType,
                                       String accessToken, Bundle options) {
        accessTokenCounter = accessTokenCounter + 1;
        SignInResult signInResult = new SignInResult();
        signInResult.isSuccessful = true;
        synchronized (this) {
            try {
                this.wait(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if ((accessTokenCounter > ACCESS_TOKEN_EXPIRATION_COUNTER || demoCounter > DEMO_COUNTER)) {
            signInResult.isSuccessful = false;
            signInResult.isAccessTokenExpired = true;
            if (demoCounter < DEMO_COUNTER) {
                signInResult.errMessage = "Access token is expired";
                return signInResult;
            }
        }
        return signInResult;
    }

    @Override
    public SignUpResult signUpToServer(Context context, Account account, String authTokenType,
                                       String refreshToken, Bundle options) {
        SignUpResult signUpResult = new SignUpResult();
        synchronized (this) {
            try {
                this.wait(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        refreshTokenCounter = refreshTokenCounter + 1;
        signUpResult.isSuccessful = true;
        signUpResult.accessToken = "ACCESS_TOKEN_NO_" + accessTokenNo;
        signUpResult.refreshToken = "REFRESH_TOKEN_NO_" + refreshTokenNo;
        if (demoCounter > DEMO_COUNTER) {
            signUpResult.isSuccessful = false;
            signUpResult.errMessage = "You have reached your limit of using the demo version. " +
                    "Please buy it for further usage";
            return signUpResult;
        }
        if (refreshTokenCounter > REFRESH_TOKEN_EXPIRATION_COUNTER) {
            refreshTokenCounter = 0;
            signUpResult.isSuccessful = false;
            signUpResult.errMessage = "User credentials have expired, please login again";
            return signUpResult;
        }
        if (accessTokenCounter > ACCESS_TOKEN_EXPIRATION_COUNTER) {
            accessTokenCounter = 0;
            accessTokenNo = accessTokenNo + 1;
            signUpResult.accessToken = "ACCESS_TOKEN_NO_" + accessTokenNo;
        }
        return signUpResult;
    }

    @Override
    public RegisterResult registerInServer(Context context, Account account, String password,
                                           String authTokenType, String[] requiredFeatures,
                                           Bundle options) {
        RegisterResult registerResult = new RegisterResult();
        registerResult.isSuccessful = false;
        synchronized (this) {
            try {
                this.wait(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if (true) {  // password is checked here and, if true, refresh token is generated for the
            // user
            refreshTokenNo = refreshTokenNo + 1;
            accessTokenNo = accessTokenNo + 1;
            registerResult.isSuccessful = true;
            registerResult.refreshToken = "REFRESH_TOKEN_NO_" + refreshTokenNo;
        }
        return registerResult;
    }

    @Override
    public boolean setDoesCallbackRunInBackgroundThread() {
        return false;
    }
}

परिणाम

निम्नलिखित क्रियाकलाप में कार्रवाई दिखाता है। आप here पूर्ण ट्यूटोरियल पा सकते हैं और इस बारे में एंड्रॉइड में AccountManager कैसे मेरी वेबसाइट से इन तीन पदों में काम करता है: भाग 1 , भाग 2 , भाग 3

मैं अपने ऐप के लिए खाता बनाने की कोशिश कर रहा हूं, जहां मैं अपने खाते के खिलाफ फेसबुक, वीबर, व्हाट्सएप इत्यादि के खिलाफ अपने संपर्क कर पाऊंगा। मैं चाहता हूं कि सेटिंग्स के खाता अनुभाग में मेरा खाता दिखाई दे। कोई विचार? मैंने बहुत कुछ किया है, लेकिन शुरू करने के लिए सही जवाब नहीं मिला। कृपया मदद करे। मैंने खाता बनाने की कोशिश की है जो नीचे है। जो मुझे एक त्रुटि के लिए प्रेरित करता है।

Account account = new Account("Title", "com.package.nom");
               String password = "password";

               AccountManager accountManager =
                       (AccountManager) MainPanel.this.getSystemService(
                               ACCOUNT_SERVICE);
               accountManager.addAccountExplicitly(account, password, null);

यहां एक कोड छीन लिया गया है, मैं इसे कर रहा हूं (जर्मन commetns के लिए खेद है) मैनिफेस्ट फ़ाइल में प्रोपर अनुमतियों को सेट करना न भूलें।

/**
 * ueberprueft, ob es den account fuer diese app schon gibt und legt ihn
 * gegebenenfalls an.
 * 
 * @param none
 * @return void
 */
public void verifyAccount() {
    if (debug)
        Log.i(TAG, "verifyAccount() ");

    boolean bereitsAngelegt = false;
    String accountType;
    accountType = this.getPackageName();

    AccountManager accountManager = AccountManager
            .get(getApplicationContext());
    Account[] accounts = accountManager.getAccounts();
    for (int i = 0; i < accounts.length; i++) {
        if (debug)
            Log.v(TAG, accounts[i].toString());
        if ((accounts[i].type != null)
                && (accounts[i].type.contentEquals(accountType))) {
            bereitsAngelegt = true;
            if (debug)
                Log.v(TAG, "verifyAccount(): bereitsAngelegt "
                        + accounts[i].type);
        }
    }

    if (!bereitsAngelegt) {
        if (debug)
            Log.v(TAG, "verifyAccount(): !bereitsAngelegt ");

        // This is the magic that addes the account to the Android Account
        // Manager

        AccountManager accMgr = AccountManager.get(this);

        String password = "some_password";

        if (debug)
            Log.d(TAG, "verifyAccount(): ADD: accountName: "
                    + Konst.accountName + " accountType: " + accountType
                    + " password: " + password);

        final Account account = new Account(Konst.accountName, accountType);
        if (debug)
            Log.v(TAG, "verifyAccount(): nach final Account account ");
        try {
            accMgr.addAccountExplicitly(account, password, null);
        } catch (Exception e1) {
            if (debug)
                Log.v(TAG, "verifyAccount(): Exception e1 " + e1.toString());
            this.finish();
        }
        if (debug)
            Log.v(TAG,
                    "verifyAccount(): nach accMgr.addAccountExplicitly() ");
    } else {
        if (debug)
            Log.v(TAG, "verifyAccount(): bereitsAngelegt ");
    }
} // end of public void verifyAccount()

मुझे उम्मीद है कि यह थोड़ा सा मदद करता है।


प्रोग्राम को प्रोग्रामेटिक रूप से बनाने में सक्षम होने के लिए आपको एकाधिक घटकों को सेट करने की आवश्यकता है। आप की जरूरत है:

  • एक खाता प्रमाणीकरणकर्ता
  • खाता प्रमाणीकरणकर्ता तक पहुंच प्रदान करने के लिए एक सेवा
  • कुछ अनुमतियां

प्रमाणीकरणकर्ता

प्रमाणीकरणकर्ता एक ऐसा ऑब्जेक्ट है जो खाता प्रकार और स्वाभाविकता (यानी लिनक्स-उपयोगकर्ता) के बीच मैपिंग करेगा, जिसका प्रबंधन करने के अधिकार हैं।

एक्सएमएल में एक प्रमाणीकरण घोषित किया जाता है:

  • एक फ़ाइल res/xml/authenticator.xml बनाएँ

निम्नलिखित सामग्री के साथ:

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

खाता टाइप करें नोट: जब आप खाता बनाते हैं तो इसे कोड में पुन: उपयोग किया जाना चाहिए। आइकन और लेबल का उपयोग "सेटिंग्स" ऐप द्वारा उस प्रकार के खातों को प्रदर्शित करने के लिए किया जाएगा।

खाता प्रमाणीकरण कार्यान्वित करना

ऐसा करने के लिए आपको AbstractAccountAuthenticator को विस्तारित करना होगा। खाता डेटा तक पहुंचने के लिए इसका उपयोग तीसरे पक्ष के ऐप द्वारा किया जाएगा।

निम्नलिखित नमूना तीसरे पक्ष के ऐप तक पहुंच की इजाजत नहीं देता है और इसलिए प्रत्येक विधि का कार्यान्वयन छोटा होता है।

public class CustomAuthenticator extends AbstractAccountAuthenticator {

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

    @Override
    public Bundle addAccount(AccountAuthenticatorResponse accountAuthenticatorResponse, String s, String s2, String[] strings, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle editProperties(AccountAuthenticatorResponse accountAuthenticatorResponse, String s) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle confirmCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle getAuthToken(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public String getAuthTokenLabel(String s) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle updateCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String[] strings) throws NetworkErrorException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }
}

सेवा प्रकार का खुलासा करने वाली सेवा

उस प्रकार के खातों में हेरफेर करने के लिए एक सेवा बनाएं:

public class AuthenticatorService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        CustomAuthenticator authenticator = new CustomAuthenticator(this);
        return authenticator.getIBinder();
    }
}

अपने मैनिफेस्ट में सेवा घोषित करें :

<service android:name="com.company.demo.account.AuthenticatorService" android:exported="false">
        <intent-filter>
            <action android:name="android.accounts.AccountAuthenticator"/>
        </intent-filter>
        <meta-data
            android:name="android.accounts.AccountAuthenticator"
            android:resource="@xml/authenticator"/>
    </service>

यहां, प्रमाणीकरणकर्ता घोषित करने वाले XML संसाधन का संदर्भ देने वाला फ़िल्टर और मेटा-डेटा मुख्य बिंदु हैं।

अनुमतियां

अपने मैनिफेस्ट में निम्नलिखित अनुमतियां घोषित करना सुनिश्चित करें

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

(इस पोस्ट में प्रस्तुत नमूना कोड के लिए सभी आवश्यक नहीं हैं, लेकिन आपके पास शायद खाता प्रबंधन के बारे में कुछ और कोड होगा और अंत में वे सभी उपयोगी होंगे)

कोड में एक खाता बनाएँ

अब सब कुछ तैयार है आप निम्नलिखित कोड के साथ एक खाता बनाते हैं। ध्यान दें कि addAccountExplicitly द्वारा लौटाया गया boolean सफलतापूर्वक या विफलता के बारे में आपको सूचित करता है।

    AccountManager accountManager = AccountManager.get(this); //this is Activity
    Account account = new Account("MyAccount","com.company.demo.account.DEMOACCOUNT");
    boolean success = accountManager.addAccountExplicitly(account,"password",null);
    if(success){
        Log.d(TAG,"Account created");
    }else{
        Log.d(TAG,"Account creation failed. Look at previous logs to investigate");
    }

अंतिम सुझाव

बाहरी ऐप पर अपना ऐप इंस्टॉल न करें

यदि आपका ऐप बाहरी स्टोरेज पर स्थापित है, तो एसडीकार्ड अनमाउंट होने पर एंड्रॉइड आपके खाता डेटा को हटा देता है (क्योंकि उस खाते के प्रमाणीकरणकर्ता अब और उपलब्ध नहीं होंगे)। तो इस नुकसान से बचने के लिए (प्रत्येक रीबूट पर !!!) आपको केवल ऐच को आंतरिक स्टोरेज पर घोषित करने वाला ऐप इंस्टॉल करना होगा:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      android:installLocation="internalOnly"
      ...

परेशानी के मामले में

लॉग को ध्यान से पढ़ें, खाता प्रबंधक आपके कोड को डीबग करने में आपकी सहायता के लिए कई लॉग आउटपुट कर रहा है।





account