java - como - enviar mensaje por correo en android studio
¿Cómo agregar programáticamente una cuenta personalizada en Android? (3)
Intento crear una cuenta para mi aplicación, donde podré tener mis contactos en mi cuenta como Facebook, viber, whatsapp, etc. Quiero que mi cuenta también esté visible en la sección de la cuenta de la configuración. ¿Algunas ideas? He buscado mucho en Google, pero no he podido encontrar una respuesta correcta para comenzar. Por favor ayuda. Lo que he tratado de crear una cuenta es la siguiente. Lo que me lleva a un error.
Account account = new Account("Title", "com.package.nom");
String password = "password";
AccountManager accountManager =
(AccountManager) MainPanel.this.getSystemService(
ACCOUNT_SERVICE);
accountManager.addAccountExplicitly(account, password, null);
He escrito una library para esto, que lo libera de los quehaceres necesarios para administrar cuentas de Android, como definir un servicio encuadernado, autenticador xml, etc. Trabajar con eso es en 5 sencillos pasos:
Paso 1
Agregue esto a dependencias para build.gradle de la aplicación:
compile ''com.digigene.android:account-authenticator:1.3.0''
Paso 2
Defina su tipo de cuenta de autenticación como una cadena en strings.xml
:
<string name="auth_account_type">DigiGene</string>
Reemplace ''DigiGene'' con su propio tipo de cuenta. Esto es lo que aparece en las cuentas de Android en esta captura de pantalla .
Paso 3
Diseña tu diseño de registro para registrar a los usuarios (por ejemplo, esta imagen ):
<?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>
y MyRegistrationActivity.java
una nueva clase, digamos MyRegistrationActivity.java
, con el siguiente código:
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);
}
}
Etapa 4
Haz un diseño de entrada como 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>
Este diseño va con la siguiente clase:
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);
}
}
Paso 5
Este es el último paso en el que se implementan los métodos necesarios para conectarse al servidor con fines de registro e inicio de sesión, y luego. A continuación, al contrario que en un caso real, se burlan las conexiones del servidor, solo para demostrar la funcionalidad de la biblioteca. Puede reemplazar la siguiente implementación por la suya propia.
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;
}
}
Resultados
Lo siguiente muestra la biblioteca en acción. Puede encontrar el tutorial completo here y cómo funciona AccountManager
en Android en estas tres publicaciones de mi sitio web: parte 1 , parte 2 , parte 3 .
Necesita configurar múltiples componentes para poder crear una cuenta mediante programación. Necesitas:
- un AccountAuthenticator
- un Servicio para proporcionar acceso al Autentificador de Cuenta
- algunos permisos
El autenticador
El autenticador es un objeto que hará que la asignación entre el tipo de cuenta y la autoría (es decir, el usuario de Linux) tenga derechos para administrarlo.
Declarar un autenticador se hace en xml:
- crea un archivo
res/xml/authenticator.xml
con el siguiente contenido:
<?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"/>
Tenga en cuenta el tipo de cuenta: debe reutilizarse en el código cuando crea la cuenta. Los iconos y la etiqueta serán utilizados por la aplicación "Configuración" para mostrar las cuentas de ese tipo.
Implementando el AccountAuthenticator
Debe extender AbstractAccountAuthenticator
para hacer eso. Esto será utilizado por una aplicación de terceros para acceder a los datos de la cuenta.
La siguiente muestra no permite ningún acceso a la aplicación de terceros y, por lo tanto, la implementación de cada método es trivial.
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.
}
}
El servicio que expone el tipo de cuenta
Crea un servicio para manipular las cuentas de ese tipo:
public class AuthenticatorService extends Service {
@Override
public IBinder onBind(Intent intent) {
CustomAuthenticator authenticator = new CustomAuthenticator(this);
return authenticator.getIBinder();
}
}
Declara el servicio en tu manifiesto :
<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>
Aquí, el filtro y los metadatos que hacen referencia al recurso xml que declara el autenticador son los puntos clave.
Los permisos
En su manifiesto, asegúrese de declarar los siguientes permisos
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
(no todos son obligatorios para el código de muestra que se presenta en esta publicación, pero es probable que tenga un poco más de código sobre la administración de la cuenta y al final todos serán útiles)
Crea una cuenta en código
Ahora que todo está listo, cree una cuenta con el siguiente código. Tenga en cuenta que boolean
devuelto por addAccountExplicitly
informa sobre el éxito o el fracaso.
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");
}
Consejos finales
No instale su aplicación en el almacenamiento externo
Si su aplicación está instalada en un almacenamiento externo, es muy probable que Android elimine los datos de su Cuenta cuando se desinstale la tarjeta SD (ya que no se podrá acceder al autenticador de esa cuenta). Por lo tanto, para evitar esta pérdida (en cada reinicio), debe instalar la aplicación que declara el autenticador solo en el almacenamiento interno:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="internalOnly"
...
En caso de problemas
Lea los registros cuidadosamente, The AccountManger está sacando muchos registros para ayudarlo a depurar su código.
aquí un código cortado lo estoy haciendo (lo siento por los commetns alemanes) no se olvide de configurar los permisos propper en el archivo de manifiesto.
/**
* 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()
espero que esto ayude un poco.