Възможно ли е да се прочете запис от устройство с Android, което не е собственик?

Разработвам приложение, което трябва да може да синхронизира хранилища за данни между няколко устройства.

Не мога да разбера защо не мога да прочета запис от устройство, което не е собственик на хранилището за данни. Докато устройството на собственика на хранилището за данни може да чете същия този запис. Трябва да уточня, че хранилището за данни е създадено с разрешение EDITOR (вижте по-долу).

try {
    datastoreTitle = mDatastoreManager.createDatastore();
    datastoreTitle.setRole(DbxPrincipal.PUBLIC, DbxDatastore.Role.EDITOR);  
    } catch (DbxException e) {
        e.printStackTrace();
    }

Някой сблъсквал ли се е със същия проблем? Кодът, повдигащ този проблем, е по-долу:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);



    /**
     * Opening of the database
     */
    db = new SQliteHelper( this ) ;



    /**
     * Connection to dropbox API
     */
    mAccountManager = DbxAccountManager.getInstance(getApplicationContext(), APP_KEY, APP_SECRET);   


    // Set up the datastore manager
    if (mAccountManager.hasLinkedAccount()) {
        try {
            // Use Dropbox datastores
            mDatastoreManager = DbxDatastoreManager.forAccount(mAccountManager.getLinkedAccount());

        } catch (DbxException.Unauthorized e) {
            System.out.println("Account was unlinked remotely");
        }


    }
    if (mDatastoreManager == null) {
        // Account isn't linked yet, use local datastores
        mDatastoreManager = DbxDatastoreManager.localManager(mAccountManager);              

        AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
        alert.setTitle("Connection à Dropbox");
        alert.setMessage("L'initialisation de l'application sert à vous synchroniser avec l'espace de données partagées.\r\n"
                + "Souhaitez-vous synchroniser votre application?");

        alert.setPositiveButton("Oui", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {

            mAccountManager.startLink((Activity)MainActivity.this, REQUEST_LINK_TO_DBX);

          }
        });

        alert.setNegativeButton("Non", new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int whichButton) {

              Intent returnIntent = new Intent();
              setResult(RESULT_CANCELED, returnIntent);
              finish();


          }
        });


        alert.show();
    }

/**
 * Listener
 */

mDatastoreManager.addListListener(new DbxDatastoreManager.ListListener() {
    @Override
    public void onDatastoreListChange(DbxDatastoreManager dbxDatastoreManager) {

List<TitleList> listInBDD = db.getTitleSQliteHelper(); 
Set<DbxDatastoreInfo> datastorePresent = null;
try {
    datastorePresent = mDatastoreManager.listDatastores();
} catch (DbxException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}
Iterator<DbxDatastoreInfo> mdbxDatastoreInfoIterator = datastorePresent.iterator() ;

while (mdbxDatastoreInfoIterator.hasNext()){

    DbxDatastoreInfo mdbxDatastoreInfo = mdbxDatastoreInfoIterator.next();
    boolean find = false ;
    Log.d("Test 1 - delete Datastore =>  mdbxDatastoreInfo.id :" , mdbxDatastoreInfo.id ) ;

    for (TitleList titleFound : listInBDD){
        if (titleFound.idDbx.equals(mdbxDatastoreInfo.id)){
            Log.d("Test 2 - delete Datastore =>  TitleList :" , titleFound.nom.toString() ) ;

            find = true ;
        }
    }

    /**
     * Problem comes below
     */


    if ( !find ){
        Log.d("Delete absent datastore inside of the BDD : " , mdbxDatastoreInfo.id ) ;
        try {

            DbxDatastore dbxStore = mDatastoreManager.openDatastore(mdbxDatastoreInfo.id);
            // Toast to check that the datastores have been found
            Toast.makeText(MainActivity.this, dbxStore.getId(), Toast.LENGTH_LONG).show();
            DbxTable tab = dbxStore.getTable("table_de_courses"); // All is fine up to here, "tab" seems empty for a device which is not the owner of the database
            QueryResult mResults = tab.query(); 
            Iterator<DbxRecord> mRecord = mResults.iterator();

            // When the device is not the owner of the database, the code stops at this while condition
            while (mRecord.hasNext()){

                DbxRecord tmpRecord = mRecord.next(); 
                Set<String> fieldList = tmpRecord.fieldNames();
                Iterator<String> fieldNameList = fieldList.iterator();

                while (fieldNameList.hasNext()){

                    String str = fieldNameList.next();

                    if ( str.equalsIgnoreCase("titre") ){
                            TitleList tit = new TitleList(tab.get("titre").getString("titre"));
                            tit.setConnectDropbox();
                            tit.setIdDbx(mdbxDatastoreInfo.id);
                            db.addLists(tit);
                        }

                }

            }


        } catch (DbxException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

АКТУАЛИЗАЦИЯ

Искам да дам допълнително обяснение по моя проблем. Взимам практичен случай, за да опиша как трябва да работи приложението ми:

  • A user opens the app from his device
    • He connects to the dropbox API (He's connecting with an "APP_KEY and APP_SERVICE"),
    • Той създава хранилище за данни вътре в приложението dropbox,
    • И след това той създава записи (като един от тях съдържа поле, наречено "titre"),
  • Потребител B отваря приложението от друго устройство,

    • He connects to the same dropbox API (He's connecting with the same couple of "APP_KEY and APP_SERVICE"),
    • Благодарение на слушателя приложението му се синхронизира, за да покаже на екрана му новото хранилище за данни, създадено от Потребител (сигурен съм, че слушателят върши работата си, защото гледам идентификаторите на хранилището благодарение на Toast [вижте кода]),

      • Problem: the datastore will never be displayed because the field called "titre" is not found out inside of the listener (see the code content).

В режим на отстраняване на грешки виждам как кодът пропуска тази част от кода (вижте по-долу). Докато има записи, като един от тях съдържа полето "titre"!

while (mRecord.hasNext()){ 
...

Надявам се данните ми да са по-ясни, не се колебайте да ме попитате за допълнителна информация. Благодаря ако можете да ми помогнете!

PS: още една подробност, потребителите трябва да се свържат с dropbox с една и съща поща и парола, за да споделят своите хранилища за данни. В противен случай те не могат да споделят своите хранилища за данни (въпреки това е, което разбрах). Правя ли грешка тук?


person FrancNovation    schedule 01.11.2014    source източник
comment
В отговор на P.S.: Не, потребителите не трябва (и не трябва) да споделят потребителско име и парола, за да споделят хранилища за данни. Този ред: datastoreTitle.setRole(DbxPrincipal.PUBLIC, DbxDatastore.Role.EDITOR); задава разрешенията за това хранилище за данни, така че всеки потребител на Dropbox, който има ID на хранилището за данни, може да го редактира. Те могат и трябва да го правят, като използват собствените си акаунти, в които са влезли със собствените си потребителски имена и пароли.   -  person Greg    schedule 03.11.2014


Отговори (1)


Не следя напълно какво се опитвате да направите тук, но някои предложения:

  • Ако един и същи потребител е влязъл и на двете устройства, не е необходимо да задавате ролята. Вие сте собственик на всяко устройство. Просто дайте време на мрежата да се синхронизира.

  • По принцип друго устройство ще трябва да изчака известно време, преди да бъде видимо в списъка ви с хранилища за данни; след това го отваряте и след това трябва да изчакате отново, докато се появи съдържанието.

Използването на слушатели е добър начин да следите за тези събития.

АКТУАЛИЗАЦИЯ: Мисля, че почти стигнахте. Очаква се веднага след като хранилището за данни се появи в списъка, когато го отворите, то е празно. Актът на отварянето му кара библиотеката да започне да изтегля съдържанието във фонов режим. Когато това изтегляне завърши (а понякога и когато е само частично завършено), вашият слушател ще бъде извикан отново. Така че вашият слушател трябва просто да се откаже, ако не намери очаквания "titre" запис и по-късно обаждане ще го намери.

АКТУАЛИЗИРАНЕ СЪЩО: Ако искате различни потребители (използващи различни акаунти в Dropbox) да споделят хранилище за данни, трябва да зададете публичната роля, но трябва да направите и нещо друго: собственик (създател) на хранилището за данни трябва по някакъв начин да предаде идентификатора на хранилището за данни на другите потребители и (това е важната част!) техният екземпляр на приложението трябва да извика openDatastore() с този идентификатор. Докато потребителят не извика openDatastore(), това хранилище за данни няма да се показва в списъка Datastores() на този потребител.

Късмет!

person Guido van Rossum    schedule 02.11.2014
comment
Съжалявам, ако не съм ясен. Това, което искам, е да позволя на различни потребители да се свързват с едно приложение, създадено на платформата за разработчици на dropbox (под раздела App Console). Ще актуализирам въпроса си, за да изясня проблема си (актуализирам и кода, защото всъщност този код се извиква от слушател). Благодаря за вашата помощ! - person FrancNovation; 03.11.2014