Java Android-两个应用程序之间的SharedReference无法有效工作

Java Android-两个应用程序之间的SharedReference无法有效工作,java,android,kotlin,sharedpreferences,android-file,Java,Android,Kotlin,Sharedpreferences,Android File,我使用Android中的SharedReferences在同一个项目中的两个应用程序之间交换简单数据。我的目的是创建一个“配置应用程序”(应用程序a),以保存一些值,并通过SharedReferences类使用的共享文件使它们可访问应用程序B。应用程序A必须允许用户更新再次启动应用程序的值,应用程序B应该看到这些更改 通过在两个应用程序中声明以下内容,我的所有应用程序都与同一个应用程序工作: android:sharedUserLabel="@string/user_id" android:sh

我使用Android中的SharedReferences在同一个项目中的两个应用程序之间交换简单数据。我的目的是创建一个“配置应用程序”(应用程序a),以保存一些值,并通过SharedReferences类使用的共享文件使它们可访问应用程序B。应用程序A必须允许用户更新再次启动应用程序的值,应用程序B应该看到这些更改

通过在两个应用程序中声明以下内容,我的所有应用程序都与同一个应用程序工作:

android:sharedUserLabel="@string/user_id"
android:sharedUserId="sos.app"
这允许我的应用程序使用相同的数据。因此,首先我启动appa,然后引入值并将数据提交到文件中。然后我启动应用程序B,通过packageContent访问SharedReferences,并正确获取我的值

当我再次启动应用程序A和应用程序B以更新值时,会出现我的问题。应用程序A中的所有更改都是正确的(我在SharedReferences中看到了更改),但当我再次启动应用程序B时,它将访问以前的值而不是新值

这很奇怪。看起来Android持有我的SharedReferences实例引用,当应用程序B再次启动时,它不会通过GetSharedReferences方法再次转到共享文件

这是应用程序A中的相关代码:

//Instance of SharedPreferences made in onCreate method
sharedPreferences = getSharedPreferences("my.configuration.file", Context.MODE_PRIVATE)
//Function to insert values in sharedPreferences
fun addConfigItemToSharedPreferences(itemToBeSaved: String){

            with (sharedPreferences.edit()) {
                putString(keyItemsList[configItemToBeAddedCounter], itemToBeSaved)
                commit()
            }
        }
这是应用程序B(onCreate方法内部)中的相关代码:

val packageContext=createPackageContext(“com.televes.angrod.configurationapp”,0)
val SharedReferences=packageContext.GetSharedReferences(“my.configuration.file”,Context.MODE\u PRIVATE)
val MapOfReferences:Map=SharedReferences.all

我的方法正确吗?或者我应该使用另一种机制在应用程序之间共享数据吗?

之前,您可以通过将MODE\u PRIVATE更改为MODE\u WORLD\u READABLE或MODE\u WORLD\u WRITABLE来解决这一问题,但现在它已被弃用

来自官方文件():

注意:MODE_WORLD_可读和MODE_WORLD_可写模式 自API级别17以来已被弃用。从Android 7.0(API)开始 级别24),如果您使用它们,Android会抛出SecurityException。如果你的 应用程序需要与其他应用程序共享私人文件,它可能使用 带有标志\u GRANT\u READ\u URI\u权限的文件提供程序。更多 有关详细信息,请参见共享文件

所以,您现在必须使用FileProvider

您可以在此处了解有关FileProvider的更多信息:


请使用内容提供商在应用程序之间共享数据。这就是推荐的Android模式:

我找到了自己的解决方案

最后,我决定将我所有的应用程序加入到同一个应用程序中。我只是在同一个清单中声明了每个活动,然后它们都共享相同的文件目录和权限。由于缓存值的问题,我还使用了直接文件访问而不是共享首选项。我还实现了一个文件观察员,以便在每个应用程序中获得有关文件更改的通知:

class FileObserver(val context: MyWatchFaceSOSApp.Engine, absolutePath: String) : FileObserver(absolutePath, FileObserver.MODIFY) {

    val TAG = "FileObserver"

    override fun onEvent(event: Int, path: String?) {

        //data was written to a file
        if (FileObserver.MODIFY and event != 0) {
            Log.i(TAG, "Wohoo. El archivo se ha actualizado!")
            Log.i(TAG, "Iniciando actualización de parámetros del WATCHFACE")
            context.cancelAndPurgePresenceReportService()
            context.updateConfigurationParams()
            context.setUpTimeBetweenPresenceReportMsgs()
            context.startPresenceReportService()
        }
    }
}
所以现在我使用一个文件管理器来执行读/写功能。我在堆栈溢出中找到了它,并做了自己的更改。 仅供分享:

public class FileManagerUtility {

    private static String TAG = "FileManagerUtility";

    public static void writeSettings(Context context, Map<String, String> watchSettings) {

        File appDirectory = new File(context.getFilesDir(), "watchsettings");
        String file = "settings.txt";

        if (!appDirectory.exists()) {
            appDirectory.mkdirs();
        }

        File fileName = new File(appDirectory, file);

        FileOutputStream fos = null;
        ObjectOutputStream out = null;
        try {
            Log.i(TAG, "Escribiendo en fichero: " + fileName.getAbsolutePath());

            fos = new FileOutputStream(fileName);
            out = new ObjectOutputStream(fos);
            out.writeObject(watchSettings);
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (fos != null)
                    fos.flush();
                fos.close();
                if (out != null)
                    out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            Log.i(TAG, "Se ha escrito correctamente en el fichero: " + fileName.getAbsolutePath());
            Log.i(TAG, "Contenido del fichero: " + watchSettings.toString());
        }
    }

    @SuppressWarnings("unchecked")
    public static Map<String, String> readSettings(Context context) {

        Map<String, String> watchSettings;

        File appDirectory = new File(context.getFilesDir(), "watchsettings");
        String file = "settings.txt";

        if (!appDirectory.exists()) return null; // File does not exist

        File fileName = new File(appDirectory, file);

        FileInputStream fis = null;
        ObjectInputStream in = null;
        try {
            Log.i(TAG, "Leyendo de fichero: " + fileName.getAbsolutePath());
            fis = new FileInputStream(fileName);
            in = new ObjectInputStream(fis);
            Map<String, String> myHashMap = (Map<String, String> ) in.readObject();
            watchSettings = myHashMap;
            return watchSettings;

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (StreamCorruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {

            try {
                if(fis != null) {
                    fis.close();
                }
                if(in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
公共类文件管理性{
私有静态字符串TAG=“filemanagerubility”;
公共静态无效写入设置(上下文上下文、映射监视设置){
File appDirectory=新文件(context.getFilesDir(),“watchsettings”);
String file=“settings.txt”;
如果(!appDirectory.exists()){
appDirectory.mkdirs();
}
文件名=新文件(appDirectory,File);
FileOutputStream=null;
ObjectOutputStream out=null;
试一试{
Log.i(标记“Escribiendo en fichero:+fileName.getAbsolutePath());
fos=新文件输出流(文件名);
out=新对象输出流(fos);
out.writeObject(watchSettings);
}捕获(IOEX异常){
例如printStackTrace();
}最后{
试一试{
如果(fos!=null)
fos.flush();
fos.close();
if(out!=null)
out.flush();
out.close();
}捕获(例外e){
e、 printStackTrace();
}
Log.i(标记为“Se ha escrito correctante en el-fichero:+fileName.getAbsolutePath());
Log.i(标记为“Contenido del fichero:+watchSettings.toString());
}
}
@抑制警告(“未选中”)
公共静态地图读取设置(上下文){
地图设置;
File appDirectory=新文件(context.getFilesDir(),“watchsettings”);
String file=“settings.txt”;
如果(!appDirectory.exists())返回null;//文件不存在
文件名=新文件(appDirectory,File);
FileInputStream fis=null;
ObjectInputStream in=null;
试一试{
Log.i(标记“leyendodefichero:+fileName.getAbsolutePath());
fis=新文件输入流(文件名);
in=新的ObjectInputStream(fis);
在.readObject()中映射myHashMap=(Map);
watchSettings=myHashMap;
返回手表设置;
}catch(filenotfounde异常){
e、 printStackTrace();
}捕获(StreamCorruptedException e){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}catch(classnotfounde异常){
e、 printStackTrace();
}捕获(例外e){
e、 printStackTrace();
}最后{
试一试{
如果(fis!=null){
fis.close();
}
if(in!=null){
in.close();
}
}捕获(IOE异常){
e、 printStackTrace();
}
}
返回null;
}
}
就这样!我将每个配置值保存在映射中,以便快速访问数据,这也很容易从文件中读取/写入数据


希望有帮助

我已经自己解决了!最后,我决定将我所有的应用程序加入到同一个应用程序中。我只是申报
public class FileManagerUtility {

    private static String TAG = "FileManagerUtility";

    public static void writeSettings(Context context, Map<String, String> watchSettings) {

        File appDirectory = new File(context.getFilesDir(), "watchsettings");
        String file = "settings.txt";

        if (!appDirectory.exists()) {
            appDirectory.mkdirs();
        }

        File fileName = new File(appDirectory, file);

        FileOutputStream fos = null;
        ObjectOutputStream out = null;
        try {
            Log.i(TAG, "Escribiendo en fichero: " + fileName.getAbsolutePath());

            fos = new FileOutputStream(fileName);
            out = new ObjectOutputStream(fos);
            out.writeObject(watchSettings);
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (fos != null)
                    fos.flush();
                fos.close();
                if (out != null)
                    out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            Log.i(TAG, "Se ha escrito correctamente en el fichero: " + fileName.getAbsolutePath());
            Log.i(TAG, "Contenido del fichero: " + watchSettings.toString());
        }
    }

    @SuppressWarnings("unchecked")
    public static Map<String, String> readSettings(Context context) {

        Map<String, String> watchSettings;

        File appDirectory = new File(context.getFilesDir(), "watchsettings");
        String file = "settings.txt";

        if (!appDirectory.exists()) return null; // File does not exist

        File fileName = new File(appDirectory, file);

        FileInputStream fis = null;
        ObjectInputStream in = null;
        try {
            Log.i(TAG, "Leyendo de fichero: " + fileName.getAbsolutePath());
            fis = new FileInputStream(fileName);
            in = new ObjectInputStream(fis);
            Map<String, String> myHashMap = (Map<String, String> ) in.readObject();
            watchSettings = myHashMap;
            return watchSettings;

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (StreamCorruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {

            try {
                if(fis != null) {
                    fis.close();
                }
                if(in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}