2013-09-29 2 views
3

Я как бы начинающий в Android-программировании. Я пытался заставить Dropbox интегрироваться в [начало] приложения, которое я пишу. Я выполнил инструкции и посмотрел на базовый пример DBRoulette, который поставляется с Dropbox API.Android Dropbox API не сохраняет логин

Проблема, с которой я сталкиваюсь, заключается в том, что я вхожу в Dropbox (через веб-браузер), а затем подтверждаю, что приложение может использовать папку Dropbox App ... Для этого сеанса он работает нормально, но затем, когда я закрываю приложение полностью и открыть его снова, меня попросят снова войти в систему! Я определенно не хочу, чтобы снова вводить все мои файлы для входа в Dropbox, даже если это только для целей отладки. Интересно, что DBRoulette отлично работает, мне не нужно входить в систему каждый раз! И я скопировал большую часть функционального кода из этого примера.

В то время как мы находимся в этом, что именно содержат/делают AccessTokens? Сохраняют ли они информацию для создания авторизованного сеанса? Является ли эта информация отличной от ключевого/секретного компилятора приложения, которое я получаю с сайта разработчика Dropbox? Я думаю, что это моя ошибка, но я не уверен.

Вот активность:

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

Любая помощь приветствуется!

+0

Я использую Dropbox API для Android, и это не выглядит знакомым. Вы используете HTTP API? – cYrixmorten

+0

@cYrixmorten Я использую API Dropbox Core https://www.dropbox.com/developers/core/start/android – flyingsilverfin

+0

Я вижу, я использую API Dropbox Sync https://www.dropbox.com/developers/sync, и у меня не возникло проблем, кроме того, что я заставил его загрузить все несинхронизированные файлы, которые он не предназначен специально для этого, поэтому пришлось прыгать на некоторые обручи. – cYrixmorten

ответ

5

Основная идея использования DropboxApi: в первый раз, когда вы подключились, вы должны получить секретные ключи, в следующий раз вы должны использовать эти ключи для доступа без подтверждения через браузер.

т.е. в методе onResume вы должны использовать эту линию

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

где DropboxAPI mDBApi;

Затем необходимо сохранить данные из

AccessTokenPair tokens 

в SQLite или SharedPrefs.

Затем вы должны использовать метод как это:

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

...

является класс Конфигурация доступности, где я хранятся ключи через ORMLite:

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

И последняя вещь: когда ты получили все ключи, которые вы не должны запускать

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

просто использовать mDBApi для ваших целей, как «mDBApi.putFile (некоторые данные)»

Примечание: Вам только нужно сделать startAuthentication() один раз, Вам не нужно запускать его уполномочить пара ключей от фактического входа.

+0

Я попытался изменить то, что у меня выше (TokenPair) на AccessTokenPair, и он все еще не поддерживает ключи доступа также, я предполагаю, что SharedPrefs зашифрованы? В противном случае кто-то мог бы прочитать их и получить доступ к моей папке с папками? – flyingsilverfin

+0

проверить обновленный ответ. В моем случае я использую базу данных ORMLite для сохранения ключей. – Aleksandr

+0

chech final one update – Aleksandr

4

Я знаю, что это старый вопрос, но ответ на него на всякий случай, когда кто-то наткнулся на него.

Что касается основной описанной проблемы - что вы должны войти в Dropbox снова каждый раз, это просто потому, что у вас есть эта линия ближе к концу OnCreate()

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

startAuthentication() всегда начинается новый поток «входа», независимо от того, у вас уже есть действующий сеанс или нет. По этой причине вы НЕ должны вызывать его каждый раз.

Принятый ответ хорош, но вы можете избежать использования меньшего кода, сохранив accessToken. Итак, сначала, в onResume() после finishAuthentication() вы бы сохранить маркер доступа, как этот

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

Тогда метод getDropboxAPI() предложил @Alexandr должен выглядеть следующим образом

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

Это также хорошая идея создать вспомогательный метод, подобный этому, чтобы проверить, правильно ли инициализирован Dropbox, прежде чем использовать его для реальной работы, например, при загрузке или загрузке файлов.

public boolean isDropboxLinked() { 
    return mDBApi != null && (mDBApi.getSession().isLinked() || mDBApi.getSession().authenticationSuccessful()); 
} 
+0

Отличный ответ, сеньор. – Sipty