Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在两个不同的android应用程序之间共享SharedReferences文件?_Android_Android Intent_Sharedpreferences_Android Context - Fatal编程技术网

如何在两个不同的android应用程序之间共享SharedReferences文件?

如何在两个不同的android应用程序之间共享SharedReferences文件?,android,android-intent,sharedpreferences,android-context,Android,Android Intent,Sharedpreferences,Android Context,我已经为此挣扎了一段时间。基本上,我想让两个应用程序(总是一起安装)共享首选项,其中一个只是在后台运行的服务,需要使用首选项(应该拥有首选项,但实际上只需要读取它们)另一个应用程序是前端UI应用程序,需要能够写入另一个应用程序拥有的首选项文件。该服务将在后台进行操作(这可能由首选项决定),用户界面将允许用户编辑首选项并查看来自该服务的一些信息。但是,它们将是不同的软件包/应用程序 我尝试了以下内容,这让我对如何在一个应用程序中设置可供另一个应用程序读取的首选项有了一个很好的了解。本质上,我通过m

我已经为此挣扎了一段时间。基本上,我想让两个应用程序(总是一起安装)共享首选项,其中一个只是在后台运行的服务,需要使用首选项(应该拥有首选项,但实际上只需要读取它们)另一个应用程序是前端UI应用程序,需要能够写入另一个应用程序拥有的首选项文件。该服务将在后台进行操作(这可能由首选项决定),用户界面将允许用户编辑首选项并查看来自该服务的一些信息。但是,它们将是不同的软件包/应用程序

我尝试了以下内容,这让我对如何在一个应用程序中设置可供另一个应用程序读取的首选项有了一个很好的了解。本质上,我通过
myContext=createPackageContext(“com.example.package”,context.MODE\u WORLD\u READABLE+context.MODE\u WORLD\u WRITEABLE)创建了一个新的上下文
然后调用
myContext.getSharedReferences(“pref\u name”,Context.MODE\u WORLD\u READABLE+Context.MODE\u WORLD\u WRITEABLE)
但是,我无法从外部应用程序-(SharedReferences.Editor)成功写入首选项。commit()返回false,并且我在logcat中收到一条关于无法编辑pref_name.xml.bak的警告


我如何才能成功地设置我的应用程序,使它们都可以读写相同的首选项文件(存储在其中一个的数据文件夹中)?

首先,我应该注意,这不是官方支持的,尽管将来可能会有一种支持的方式添加到Android中(即,它不会是这种方法)(两项索赔的来源:见本报告第二段)

同样,这是不受支持的,很可能是不稳定的。我做这项实验主要是为了看看它是否可行;如果您计划将此方法实际合并到应用程序中,请格外小心。

但是,如果满足一些要求,则似乎可以在应用程序之间共享首选项。首先,如果希望应用程序B能够访问应用程序a的首选项,则应用程序B的包名必须是应用程序a包名的子项(例如,应用程序a:
com.example.pkg
应用程序B:
com.example.pkg.stuff
)。此外,它们不能同时访问该文件(我假设在活动之间访问它们时适用相同的规则,如果要确保原子访问,则必须使用额外的保护措施,如.wait()和.notify(),但我在此不赘述)

注意:所有这些都可以在2.2和2.3.3的模拟器上运行——我还没有在设备或android版本上进行过广泛的测试




在将拥有首选项的应用程序中要做的事情(上面的应用程序A):

1.)声明SharedReferences文件 这相当简单。只需为SharedReferences文件和类中的编辑器声明几个变量,并在onCreate方法中实例化它们。现在,您可以在首选项中添加一个字符串,以确保其他应用程序可以正确读取该字符串

public class stuff extends Activity {
    SharedPreferences mPrefs = null;
    SharedPreferences.Editor mEd= null; 
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mPrefs = (getApplicationContext()).getSharedPreferences("svcprefs", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);
        mEd = mPrefs.edit();
        mEd.putString("test", "original send from prefs owner");
        mEd.commit();
2.)设置备份文件 GetSharedReferences方法似乎在检查要从中加载首选项的.bak文件。这就是为什么它在文档中说它不能跨多个过程工作;为了最大限度地减少I/O,它会在抓取Pref时加载它们一次,并且仅在关闭应用程序/活动时备份它们。但是,如果您从外部应用程序调用此应用程序,您将收到一条警告,提示您没有文件夹(第一个应用程序的数据文件夹)的正确文件权限。为了解决这个问题,我们将自己创建.bak文件,并使其公开可读写。我选择这样做的方式是在我的整个类中定义三个变量

final String[] copyToBackup = { "dd", "if=/data/data/com.example.pkg/shared_prefs/prefs.xml", "of=/data/data/com.example.pkg/shared_prefs/prefs.xml.bak", "bs=1024" };
final String[] mainFixPerm = {"chmod", "666", "/data/data/com.example.pkg/shared_prefs/prefs.xml"};
final String[] bakFixPerm = {"chmod", "666", "/data/data/com.example.pkg/shared_prefs/prefs.xml.bak"};
在我的主类中创建一个函数,将这些作为参数并执行它们

public void execCommand(String[] arg0){
     try {
         final Process pr = Runtime.getRuntime().exec(arg0);
         final int retval = pr.waitFor();
         if ( retval != 0 ) {
             System.err.println("Error:" + retval);
         }
     }
     catch (Exception e) {}
}
它不太漂亮,也不太好,但很管用。 现在,在onCreate方法中(就在editor.commit()之后),您将使用三个字符串中的每一个调用此函数

execCommand(copyToBackup);
execCommand(mainFixPerm);
execCommand(bakFixPerm);
这将复制该文件,并使外部程序可以访问main.xml和.xml.bak文件。您还应该在onDestroy()中调用这三个方法,以确保在应用程序退出时正确备份数据库,并在调用应用程序中其他地方的GetSharedReferences之前调用它们(否则,它将加载.bak文件,如果另一个进程正在编辑主.xml文件,该文件可能已过期)。不过,这就是您在此应用程序中需要做的所有事情。您可以在此活动中的其他位置调用GetSharedReferences,它将从.xml文件中获取所有数据,然后允许您调用getdatatype(“键”)方法并检索它。


访问文件时要做的事情(上面的应用程序B)

1.)写入文件
这就更简单了。我在这个活动上做了一个按钮,并在它的onClick方法中设置了代码,这将把一些东西保存到共享首选项文件中。请记住,应用程序B的包必须是应用程序a包的子包。我们将基于应用程序a的上下文创建一个上下文,然后在该上下文上调用GetSharedReferences

prefsbutton.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        Context myContext = null;
        try {
            // App A's context
            myContext = createPackageContext("com.example.pkg", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);
        } catch (NameNotFoundException e) {e.printStackTrace();}

        testPrefs = myContext.getSharedPreferences("svcprefs", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);
        testEd = testPrefs.edit();
        String valueFromPrefs = testPrefs.getString("test", "read failure");
        TextView test1 = (TextView)findViewById(R.id.tvprefs);
        test1.setText(valueFromPrefs);
        testEd.putString("test2", "testback");
        boolean edit_success = testEd.commit();

这将获取我在另一个应用程序中设置的字符串,并在该应用程序的文本视图中显示它(或错误消息)。此外,它在首选项文件中设置一个新字符串并提交更改。运行此操作后,如果您的其他应用程序调用GetSharedReferences,它将从该应用程序检索包含更改的文件。

最好为该文件设置私有模式。应用程序需要使用相同的证书集签名才能共享此文件

将两个应用程序中的sharedUserId设置为相同

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hello"
android:versionCode="1"
android:versionName="1.0" 
android:sharedUserId="com.example">
....
像往常一样从SharedReference获取项目
mContext = context.createPackageContext(
                        "com.example.otherapp",
                        Context.MODE_PRIVATE);
 mPrefs = mContext.getSharedPreferences("sameFileNameHere", Activity.MODE_PRIVATE);