Java Android-两个应用程序之间的SharedReference无法有效工作
我使用Android中的SharedReferences在同一个项目中的两个应用程序之间交换简单数据。我的目的是创建一个“配置应用程序”(应用程序a),以保存一些值,并通过SharedReferences类使用的共享文件使它们可访问应用程序B。应用程序A必须允许用户更新再次启动应用程序的值,应用程序B应该看到这些更改 通过在两个应用程序中声明以下内容,我的所有应用程序都与同一个应用程序工作: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: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;
}
}