API de Dropbox de Android que no guarda el inicio de sesión

Soy una especie de principiante en la programación de Android. He estado tratando de conseguir que Dropbox se integre en [los comienzos de] una aplicación que estoy escribiendo. He seguido las instrucciones y he visto el ejemplo básico DBRoulette que viene con la API de Dropbox.

El problema que me sigue corriendo es que me registro en Dropbox (a través de navegador web) y luego confirmar que la aplicación puede utilizar su carpeta de la aplicación Dropbox … Para esa sesión funciona bien, pero luego cuando cierro la aplicación totalmente y abrirlo nuevamente, me piden que vuelva a iniciar sesión! Definitivamente no quiero tener que volver a escribir todas mis cosas de inicio de sesión de dropbox de nuevo, incluso si esto es sólo para propósitos de depuración. Lo interesante es que DBRoulette funciona bien, no tengo que iniciar sesión cada vez! Y copia copié gran parte del código funcional de ese ejemplo.

Mientras estamos en ello, ¿qué exactamente contienen / hacen los AccessTokens? ¿Guardan la información para crear una sesión autorizada? ¿Es esta información diferente de la clave de la aplicación / combo secreto que obtengo del sitio de desarrollo de Dropbox? Creo que aquí es donde está mi error, pero no estoy seguro.

Aquí está la actividad:

package com.JS.music; import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.View; import android.widget.Button; import android.widget.Toast; import com.dropbox.client2.DropboxAPI; import com.dropbox.client2.android.AndroidAuthSession; import com.dropbox.client2.session.AccessTokenPair; import com.dropbox.client2.session.AppKeyPair; import com.dropbox.client2.session.TokenPair; import com.dropbox.client2.session.Session.AccessType; public class MainActivity extends Activity { private static String TAG = "MainActivity"; private Button gotoRecordingButton; private Button libraryButton; //Dropbox final static private String APP_KEY = "xxxxxxxxxxxxx"; final static private String APP_SECRET = "xxxxxxxxxxxxxx"; final static private AccessType ACCESS_TYPE = AccessType.APP_FOLDER; private DropboxAPI<AndroidAuthSession> mDBApi; final static public String ACCOUNT_PREFS_NAME = "MusicDBPrefs"; final static public String ACCESS_KEY_NAME = "Music_DB_ACCESS_KEY"; final static public String ACCESS_SECRET_NAME = "Music_DB_ACCESS_SECRET"; private boolean mIsLoggedIn = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gotoRecordingButton = (Button) findViewById(R.id.goto_recording_button); gotoRecordingButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, RecordActivity.class); startActivity(intent); } }); libraryButton = (Button) findViewById(R.id.library_button); libraryButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } }); AndroidAuthSession session = buildSession(); mDBApi = new DropboxAPI<AndroidAuthSession>(session); mDBApi.getSession().startAuthentication(MainActivity.this); setLoggedIn(mDBApi.getSession().isLinked()); Toast msg = Toast.makeText(this, "logged in: " + isLoggedIn(), Toast.LENGTH_LONG); msg.show(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } //-------------Dropbox stuff for testing and debugging--------- @Override protected void onResume() { super.onResume(); AndroidAuthSession session = mDBApi.getSession(); // The next part must be inserted in the onResume() method of the // activity from which session.startAuthentication() was called, so // that Dropbox authentication completes properly. if (session.authenticationSuccessful()) { try { // Mandatory call to complete the auth session.finishAuthentication(); // Store it locally in our app for later use TokenPair tokens = session.getAccessTokenPair(); storeKeys(tokens.key, tokens.secret); setLoggedIn(true); } catch (IllegalStateException e) { Log.i(TAG, "Error authenticating", e); } } } //copied from dropbox API private void storeKeys(String key, String secret) { // Save the access key for later SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0); Editor edit = prefs.edit(); edit.putString(ACCESS_KEY_NAME, key); edit.putString(ACCESS_SECRET_NAME, secret); edit.commit(); } private String[] getKeys() { SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0); String key = prefs.getString(ACCESS_KEY_NAME, null); String secret = prefs.getString(ACCESS_SECRET_NAME, null); if (key != null && secret != null) { Log.i(TAG,"Got keys"); String[] ret = new String[2]; ret[0] = key; ret[1] = secret; return ret; } else { return null; } } private AndroidAuthSession buildSession() { AppKeyPair appKeyPair = new AppKeyPair(APP_KEY, APP_SECRET); AndroidAuthSession session; String[] stored = getKeys(); if (stored != null) { AccessTokenPair accessToken = new AccessTokenPair(stored[0], stored[1]); session = new AndroidAuthSession(appKeyPair, ACCESS_TYPE, accessToken); } else { session = new AndroidAuthSession(appKeyPair, ACCESS_TYPE); } return session; } public void setLoggedIn(boolean loggedIn) { mIsLoggedIn = loggedIn; } public boolean isLoggedIn() { return mIsLoggedIn; } } 

¡Cualquier ayuda apreciada!

La idea principal cuando se utiliza DropboxApi es: en la 1 ª vez cuando se conectó debe obtener claves secretas, la próxima vez que debe utilizar estas teclas para el acceso sin confirmar a través del navegador.

es decir, en onResume método que debe utilizar esta línea

 AccessTokenPair tokens = mDBApi.getSession().getAccessTokenPair(); 

donde DropboxAPI mDBApi;

A continuación, debe guardar los datos de

 AccessTokenPair tokens 

en sqlite o SharedPrefs.

Entonces debe usar un método como este:

 private DropboxAPI <AndroidAuthSession> getDropboxAPI(){ AppKeyPair appKeys = new AppKeyPair(APP_KEY, APP_SECRET); AndroidAuthSession session = new AndroidAuthSession(appKeys, ACCESS_TYPE); mDBApi = new DropboxAPI<AndroidAuthSession>(session); AccessKeys keys = dm.getAccessKeys(APP_KEY); //dm is DatabaseManager of ORMLite if (keys == null) return null; AccessTokenPair access = new AccessTokenPair(keys.getAccessKey(), keys.getAccessSecret()); mDBApi.getSession().setAccessTokenPair(access); return mDBApi; } 

AccessKeys es la clase donde almacené las claves vía ORMLite:

 @DatabaseTable public class AccessKeys { ... @DatabaseField private String accessKey; @DatabaseField private String accessSecret; @DatabaseField private String appKey; @DatabaseField private String appSecret; ...} 

Y una última cosa: cuando tienes todas las claves no debes correr

 mDBApi.getSession().startAuthentication(MainActivity.this); 

sólo usa mDBApi para tus objetivos, como "mDBApi.putFile (algunos datos)"

Nota: Sólo es necesario hacer startAuthentication () una vez, no es necesario ejecutarlo para autorizar el par de claves desde el inicio de sesión actual.

Sé que es una vieja pregunta, pero respondiéndola por si alguien tropieza con ella.

En cuanto al principal problema descrito – que tiene que iniciar sesión en Dropbox de nuevo cada vez, eso es simplemente porque tiene esta línea cerca del final de onCreate ()

 mDBApi.getSession().startAuthentication(MainActivity.this); 

startAuthentication () siempre inicia un nuevo flujo de "inicio de sesión", no importa si ya tiene una sesión válida o no. Por esta razón no deberías llamarlo cada vez.

La respuesta aceptada es buena, pero se puede salir con el uso de menos código, guardando el accessToken. Así que primero, en onResume () después de finishAuthentication () usted guardaría el accessToken como este

 String accessToken = mDBApi.getSession().getOAuth2AccessToken(); // save accessToken to SQLite or SharedPrefs or whatever 

Entonces, el método getDropboxAPI () sugerido por @Alexandr debería tener este aspecto

 private DropboxAPI <AndroidAuthSession> getDropboxAPI() { AppKeyPair appKeys = new AppKeyPair(APP_KEY, APP_SECRET); AndroidAuthSession session = new AndroidAuthSession(appKeys, ACCESS_TYPE); mDBApi = new DropboxAPI<AndroidAuthSession>(session); String savedAccessToken = // get previously saved accessToken if (!TextUtils.isEmpty(savedAccessToken)) { mDBApi.getSession().setOAuth2AccessToken(savedAccessToken); } return mDBApi; } 

También es una buena idea crear un método auxiliar como este para comprobar si Dropbox está correctamente inicializado antes de usarlo para trabajos reales, como subir o descargar archivos.

 public boolean isDropboxLinked() { return mDBApi != null && (mDBApi.getSession().isLinked() || mDBApi.getSession().authenticationSuccessful()); } 
  • Archivo de carga de Android en Google Drive y Dropbox
  • Uso de Proguard para obfuscar la aplicación Android con las bibliotecas de Dropbox.com
  • Dropbox SDK para Android: no puede encontrar AndroidAuthSession
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.