¿Cómo puedo compartir un archivo de SharedPreferences en dos aplicaciones diferentes de Android?

He estado luchando con esto por un tiempo. Básicamente, quiero tener dos aplicaciones (que siempre se instalarán juntas) compartir preferencias, una de ellas es solo un servicio que se ejecuta en segundo plano y necesita usar las preferencias (debería poseer las preferencias pero solo necesita leerlas). ) y la otra aplicación es una aplicación de interfaz de usuario de front-end que debe poder escribir en el archivo de preferencias propiedad de la otra aplicación. El servicio hará cosas en segundo plano (que puede estar determinado por las preferencias) y la IU le permitirá al usuario editar las preferencias y ver cierta información del servicio. Sin embargo, serán diferentes paquetes / aplicaciones.

Intenté seguir este tutorial que me dio una muy buena idea de cómo tener preferencias en una aplicación que puedan leer otras. Esencialmente, creo un nuevo contexto a través de myContext = createPackageContext("com.example.package",Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); y luego myContext.getSharedPreferences("pref_name", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); Sin embargo, no puedo escribir correctamente en las preferencias desde la aplicación externa – (SharedPreferences.Editor). .Commit () devuelve falso y aparece una advertencia en logcat sobre no poder editar pref_name.xml.bak.

¿Cómo puedo configurar correctamente mis aplicaciones para que ambas puedan leer y escribir en el mismo archivo de preferencias (que está almacenado en la carpeta de datos de uno de ellos)?

Es mejor configurar el modo privado para el archivo. La aplicación debe estar firmada con el mismo conjunto de certificados para compartir este archivo.

Establezca sharedUserId en ambas aplicaciones para que sean iguales.

  .... 

Obtener contexto de otro paquete:

 mContext = context.createPackageContext( "com.example.otherapp", Context.MODE_PRIVATE); mPrefs = mContext.getSharedPreferences("sameFileNameHere", Activity.MODE_PRIVATE); 

Obtenga elementos como siempre desde SharedPreference. Puedes acceder ahora.

En primer lugar, debería tener en cuenta que esto no es oficialmente compatible, aunque puede haber una forma admitida de hacerlo (es decir, NO sería este método) agregado a Android en el futuro (fuente para ambos reclamos: ver el segundo párrafo de este enlace ) .

De nuevo, esto no es compatible y es muy posiblemente inestable. Principalmente hice esto como un experimento para ver si era posible; tenga extrema precaución si planea incorporar este método en una aplicación.

Sin embargo, parece posible compartir preferencias entre aplicaciones si se cumplen algunos requisitos. En primer lugar, si desea que la aplicación B pueda acceder a las preferencias de la aplicación A, el nombre del paquete de la aplicación B debe ser hijo del nombre del paquete de la aplicación A (p. Ej., La aplicación A: com.example.pkg aplicación B: com.example.pkg.stuff ) Además, no pueden querer acceder al archivo al mismo tiempo (supongo que se aplican las mismas reglas que para acceder a ellos entre actividades, si desea garantizar el acceso atómico, deberá usar protecciones adicionales como .wait ( ) y .notify (), pero no entraré en eso aquí).

Nota: todo esto funciona en el emulador en 2.2 y 2.3.3. No he probado exhaustivamente en dispositivos o versiones de Android.

Cosas que hacer en la aplicación que será propietaria de las preferencias (Aplicación A desde arriba):

1.) Declare el archivo SharedPreferences
Esto es bastante simple. Simplemente declare un par de variables para su archivo de preferencias compartidas y el editor de su clase y cree una instancia en su método onCreate. Puede poner una cadena en las preferencias ahora que usará para asegurarse de que la otra aplicación pueda leerla correctamente.

 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.) Configurar el archivo de copia de seguridad. El método getSharedPreferences aparece para verificar que un archivo .bak cargue las preferencias. Es por eso que dice en la documentación que no funcionará en múltiples procesos; para minimizar la E / S, carga los prefs UNA VEZ cuando los agarra y solo los respalda cuando cierra su aplicación / actividad. Sin embargo, si llama a esto desde una aplicación externa, recibirá una advertencia acerca de no tener los permisos de archivo correctos para la carpeta (que es la carpeta de datos de la primera aplicación). Para solucionarlo, crearemos el archivo .bak nosotros mismos y lo haremos público / legible. La forma en que elegí hacer esto fue definir tres variables en mi clase general.

 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"}; 

y hacer una función en mi clase principal que los tomaría como argumentos y los ejecutaría

 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) {} } 

No es terriblemente bonito ni bueno, pero funciona. Ahora, en su método onCreate (justo después de editor.commit ()) llamará a esta función con cada una de las tres cadenas.

 execCommand(copyToBackup); execCommand(mainFixPerm); execCommand(bakFixPerm); 

Esto copiará el archivo y hará que los archivos principales .xml y .xml.bak sean accesibles a progtwigs externos. También debe llamar a estos tres métodos en su onDestroy () para asegurarse de que la base de datos se respalda correctamente cuando se cierra su aplicación, y además llamarlos directamente antes de llamar a getSharedPreferences en otra parte de su aplicación (de lo contrario cargará el archivo .bak que es probable que esté desactualizado si otro proceso ha estado editando el archivo principal .xml). Sin embargo, eso es todo lo que necesitas hacer en esta aplicación. Puede llamar a getSharedPreferences en otra parte de esta actividad y tomará todos los datos del archivo .xml, lo que le permite llamar a los métodos getdatatype (“clave”) y recuperarlos.

Cosas que hacer en el (los) archivo (s) de acceso (aplicación B desde arriba)

1.) Escribir en el archivo
Esto es aún más simple. Inicié un botón en esta actividad y configuré el código en su método onClick que guardará algo en el archivo de preferencias compartidas. Recuerde que el paquete de la aplicación B debe ser un elemento secundario del paquete de la aplicación A. Crearemos un contexto basado en el contexto de la Aplicación A y luego llamaremos a getSharedPreferences en ese contexto.

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

Esto toma la cadena que configuré en la otra aplicación y la muestra (o un mensaje de error) en una vista de texto en esta aplicación. Además, establece una nueva cadena en el archivo de preferencias y confirma los cambios. Después de que esto se ejecute, si su otra aplicación llama a getSharedPreferences, recuperará el archivo, incluidos los cambios de esta aplicación.

Intereting Posts