Ответ 1
Во-первых, я должен отметить, что это официально не поддерживается, хотя может быть поддержанный способ сделать это (т.е. он не был бы этим методом) добавлен в Android в будущем (источник для обеих претензий: см. второй абзац эта ссылка).
Опять же, это неподдерживается и очень возможно нестабильно. В первую очередь я сделал это как эксперимент, чтобы убедиться, что это возможно; будьте предельно осторожны, если вы планируете фактически включить этот метод в приложение.
Однако, возможно, существует возможность делиться предпочтениями между приложениями, если выполняется несколько требований. Во-первых, если вы хотите, чтобы приложение B получало доступ к настройкам приложения А, имя пакета приложения B должно быть дочерним по имени пакета приложения A (например, приложение A: com.example.pkg
приложение B: com.example.pkg.stuff
). Кроме того, они не могут одновременно получать доступ к файлу (я предполагаю, что применяются те же правила, что и для доступа к ним между действиями, если вы хотите обеспечить атомный доступ, вам придется использовать дополнительные меры защиты, такие как .wait( ) и .notify(), но я не буду вдаваться в это здесь).
Примечание: все это работает на эмуляторе на 2.2 и 2.3.3. Я не тестировался на разных устройствах или версиях Android.
Что делать в приложении, которое будет иметь предпочтения (приложение А сверху):
1.) Объявите файл SharedPreferences
Это довольно просто. Просто объявите пару переменных для файла sharedpreferences и редактора в своем классе и создайте их в своем методе 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.) Настройте файл резервной копии Метод getSharedPreferences проверяет наличие файла .bak для загрузки предпочтений. Вот почему в документации говорится, что он не будет работать через несколько процессов; чтобы минимизировать ввод-вывод, он загружает prefs ONCE, когда вы их захватываете, и только поддерживает их при закрытии приложения/активности. Однако, если вы вызываете это из внешнего приложения, вы получите предупреждение о том, что у него нет прав доступа к папке (которая является первой папкой данных приложения). Чтобы исправить это, мы собираемся сами создать файл .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);
Это скопирует файл и сделает доступным как основной файл .xml, так и .xml.bak для внешних программ. Вы также должны вызывать эти три метода в вашем onDestroy(), чтобы убедиться, что база данных была скопирована правильно, когда ваше приложение выходит, и дополнительно вызывайте их прямо до того, как вы вызываете getSharedPreferences в другом месте вашего приложения (так как в противном случае он будет загружать .bak файл, который скорее всего, устарели, если другой процесс редактирует основной .xml файл). Тем не менее, все, что вам нужно сделать в этом приложении. Вы можете вызвать getSharedPreferences в другом месте этого действия, и он будет захватывать все данные из XML файла, позволяя вам затем вызвать методы getdatatype ( "ключ" ) и получить их.
Что делать в файлах доступа (приложение B сверху)
1.) Запись в файл
Это еще проще. Я сделал кнопку на этом мероприятии и настроил код в методе onClick, который сохранил бы что-то в файле общих настроек. Помните, что пакет App B должен быть дочерним из пакета App A. Мы создадим контекст, основанный на контексте App A, а затем вызываем getSharedPreferences в этом контексте.
prefsbutton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Context myContext = null;
try {
// App A 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();
Это захватывает строку, которую я установил в другом приложении, и отображает ее (или сообщение об ошибке) в текстовом виде в этом приложении. Кроме того, он устанавливает новую строку в файле настроек и фиксирует изменения. После этого, если ваше другое приложение вызывает getSharedPreferences, оно будет извлекать файл, включая изменения из этого приложения.