SAF - 监听云中文件夹中的事件

问题描述 投票:0回答:1

我正在尝试存储访问框架,因为我想改进我的应用程序,它已经迁移到 SAF(尽管由于一些 SAF 设计缺陷或错误,我不得不放弃一些功能)。

现在我希望当用户在云中的 SAF 文件夹中执行某些操作时通知我的应用程序。

目前它纯粹是实验性的,因为通过 hack 可以通过 GDrive 获得云文件夹的 uri。

(其他云提供商似乎没有准备好SAF,如果我错了请纠正我)

我只是在他们发布完整功能之前提前工作(有一个关于该功能的错误修复请求),以便能够在系统选择器中选择云存储根目录上的文件夹。

我创建了一个简单的应用程序,用于在云上创建 SAF 文件夹(目前在云存储上无法选择)并监听事件。

package com.example.safevents;

import android.app.Activity;
import android.content.Intent;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;

import  com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {
Activity activity;
Handler handler;
Observer observer;


class Observer extends ContentObserver {

    public Observer(Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange) {
        this.onChange(selfChange, null);
        Log.d("SAF","event fired; selfchange="+selfChange);
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {

        Log.d("SAF","event fired on uri="+uri.toString()+"; selfchange="+selfChange);
    }
}

public void openPickerForFolderCreation(Activity activity, int requestCode) {

    Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
    intent.setType("vnd.android.document/directory");
    intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    activity.startActivityForResult(intent, requestCode);
}

public Uri takePermanentReadWritePermissions(Activity activity, Uri uri, int flags) {
    int takeFlags = flags
            &
            (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
            );

    ;


    ContentResolver resolver = activity.getContentResolver();
    resolver.takePersistableUriPermission(uri, takeFlags);

    return uri;

}

public boolean arePermissionsGranted(Activity activity, String uriString) {

    Uri uri = Uri.parse(uriString);


    ContentResolver resolver = activity.getContentResolver();
    List<UriPermission> list = resolver.getPersistedUriPermissions();
    for (int i = 0; i < list.size(); i++) {

        if (((Uri.decode(list.get(i).getUri().toString())).equals(Uri.decode(uriString))) && list.get(i).isWritePermission() && list.get(i).isReadPermission()) {
            return true;
        }


    }

    return false;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    activity=this;
    FloatingActionButton fab = findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
            SAFUtils.openPickerForFolderCreation(activity,0);
        }
    });
}

@覆盖 受保护无效 onDestroy() { super.onDestroy(); //重要的 getContentResolver().unregisterContentObserver(观察者); }

@Override
protected void onActivityResult(int requestCode, int resultCode,Intent returnedIntent)
{
Log.d("SAF","picker returned "+resultCode+" "+requestCode);
if (returnedIntent!=null) Log.d("SAF","intent="+returnedIntent.toString());
if (returnedIntent.getData()!=null) Log.d("SAF","uri="+returnedIntent.getData().toString());

//resultCode is -1
    if (resultCode==-1)
        if (requestCode==0)
        {

            Uri uri=SAFUtils.takePermanentReadWritePermissions(activity,returnedIntent.getData(),returnedIntent.getFlags());

            Log.d("SAF","read/write permissions="+SAFUtils.arePermissionsGranted(activity,uri.toString()));

            handler=new Handler(){};

            observer=new Observer(handler);
            getContentResolver().
                    registerContentObserver(
                            uri,
                            true,
                            observer);
        }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();


    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

我得到这个日志行:

com.example.safevents D/SAF: picker returned -1 0
com.example.safevents D/SAF: intent=Intent { dat=content://com.google.android.apps.docs.storage/document/acc=3;doc=encoded=randomalphanumericsequence= flg=0x43 }
com.example.safevents D/SAF: uri=content://com.google.android.apps.docs.storage/document/acc%3D3%3Bdoc%3Dencoded%3Dthesamealphanumericsequence%3D
com.example.safevents D/SAF: read/write permissions=true

但在创建的文件夹内进行一些简单的文件操作后,我没有收到任何事件通知。

注意 resultCode= -1。

另请注意,省略对 takePersistentPermissions 方法的调用会导致没有权限,这是因为检查它们的实用程序函数在列表中找不到 uri。

上面的代码有问题吗?

创建 SAF 云文件夹是否是一种黑客行为,无法正常工作?

是否可以进一步进行黑客攻击来强制其工作,以便提前进行粗略测试?

SAF 功能目前不可用吗?

android events google-cloud-platform picker storage-access-framework
1个回答
0
投票

观察者=新观察者(处理程序); getContentResolver()。 注册内容观察者( 乌里, 真的, 观察员); } }

© www.soinside.com 2019 - 2024. All rights reserved.