简体   繁体   English

是否可以从不是其所有者的Android设备读取记录?

[英]Is it possible to read a record from an Android device which is not the owner of it?

I'm developing an app which should be able to synchronize datastores between several devices. 我正在开发一个应该能够在多个设备之间同步数据存储的应用程序。

I cannot figure out why I cannot read a record from a device which is not the owner of the datastore. 我无法弄清楚为什么我无法从不是数据存储所有者的设备读取记录。 Whereas the owner device of the datastore can read this same record. 而数据存储区的所有者设备可以读取此相同记录。 I have to precise that the datastore has been created with the EDITOR permission (see below). 我必须精确说明该数据存储区已使用EDITOR权限创建(请参见下文)。

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

Someone has him been confronted to the same problem? 他有人遇到过同样的问题吗? The code raising this issue is below : 引发此问题的代码如下:

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

UPDATE UPDATE

I want to bring further explanation on my issue. 我想对我的问题作进一步的解释。 I take a pratical case to describe how my app should work: 我以一个实用的案例来描述我的应用程序应如何工作:

  • A user opens the app from his device 用户从他的设备打开应用
    • He connects to the dropbox API (He's connecting with an "APP_KEY and APP_SERVICE"), 他连接到保管箱API(他正在连接“ APP_KEY和APP_SERVICE”),
    • He creates a datastore inside of the dropbox app, 他在保管箱应用程序内部创建了一个数据存储区,
    • And then he creates records (with one of them containing a field called "titre" ), 然后他创建了记录(其中一个包含一个名为“ titre”字段 ),
  • B user opens the app from another device, B用户从另一台设备打开该应用,

    • He connects to the same dropbox API (He's connecting with the same couple of "APP_KEY and APP_SERVICE"), 他连接到相同的保管箱API(他使用相同的“ APP_KEY和APP_SERVICE”对连接),
    • Thanks to the listener, his app is syncing to diplay on his screen the new datastore created by the A user (I'm sure that the listener makes its job because I watch the datastore's IDs thanks to a Toast [see the code]), 多亏了侦听器,他的应用程序才得以同步以在屏幕上显示A用户创建的新数据存储区(我确信侦听器能够完成工作,因为我感谢Toast来观看数据存储区的ID [请参见代码]),

      • 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”字段(请参见代码内容)。

In debug mode I can see the code skipping this part of the code (see below). 在调试模式下,我可以看到代码跳过了这部分代码(请参见下文)。 Whereas there are records with one of them containing the "titre" field! 而有些记录包含“ titre”字段!

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

I hope my details will be clearer, don't hesitate to ask me further information. 希望我的详细信息会更清楚,不要犹豫,向我询问更多信息。 Thank you if you can help me! 谢谢您的帮助!

PS: one more detail, users have to connect to dropbox with a same mail and password to share their datastores. PS:更多细节,用户必须使用相同的邮件和密码连接到保管箱才能共享其数据存储。 Otherwise they cannot shared their datastores (nevertheless it is what I have understood). 否则,他们将无法共享其数据存储(尽管这是我所了解的)。 Am I doing a mistake here?. 我在这里做错了吗?

I'm not following completely what you're trying to do here, but some suggestions: 我没有完全遵循您在这里尝试做的事情,但是有一些建议:

  • If the same user is logged in to both devices, you don't need to set the role. 如果同一用户登录到两个设备,则无需设置角色。 You are the owner on each device. 您是每台设备的所有者。 Just give the network time to sync. 只需给网络时间同步即可。

  • In general, another device will have to wait a certain time before it is visible in your list of datastores; 通常,另一台设备必须等待一段时间才能在数据存储列表中显示。 then you open it, and then you have to wait again until the contents will appear. 然后将其打开,然后必须再次等待直到内容出现。

Using listeners is a good way to watch for these events. 使用侦听器是监视这些事件的好方法。

UPDATE: I think you're almost there. 更新:我想你快到了。 It's expected that right after the datastore appears in the list, when you open it, it is empty. 预计在数据存储出现在列表中之后,当您打开它时,它为空。 The act of opening it temms the library to start downloading the contents in the background. 打开该库的操作会限制库开始在后台下载内容。 When that download is complete (and sometimes when it is only partially complete) your listener will be called again. 该下载完成后(有时仅部分完成),您的监听器将再次被调用。 So your listener should just give up if it doesn't find the expected "titre" record and a later call will find it. 因此,如果没有找到预期的“滴定”记录,您的听众应该放弃,以后再找到它。

UPDATE TOO: If you want different users (using different Dropbox accounts) to share a datastore, you do have to set the public role, but you have to do something else too: the owner (creator) of the datastore must somehow transmit the datastore ID of the datastore to the other users, and (this is the important part!) their instance of the app must call openDatastore() with that ID. 更新:如果您希望不同的用户(使用不同的Dropbox帐户)共享数据存储,则必须设置公共角色,但您还必须做其他事情:数据存储的所有者(创建者)必须以某种方式传输数据存储其他用户的数据存储区ID,(这是重要的部分!)他们的应用程序实例必须使用该ID调用openDatastore()。 Until a user calls openDatastore() that datastore will not show in that user's listDatastores(). 在用户调用openDatastore()之前,该数据存储区不会显示在该用户的listDatastores()中。

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM