21

私はしばらくこれに苦労してきました。基本的に、2つのアプリケーション(常に一緒にインストールされます)に設定を共有させたいと思います。そのうちの1つは、バックグラウンドで実行され、設定を使用する必要があるサービスです(設定を所有している必要がありますが、実際に読み取る必要があるだけです)。 )および他のアプリは、他のアプリが所有する設定ファイルに書き込むことができる必要があるフロントエンドUIアプリです。サービスはバックグラウンドで処理を実行し(設定によって決定される場合があります)、UIを使用すると、ユーザーは設定を編集したり、サービスからの情報を表示したりできます。ただし、それらは異なるパッケージ/アプリになります。

私はこのチュートリアルに従ってみました。これにより、あるアプリで別のアプリが読み取れる設定を設定する方法についてかなり良いアイデアが得られました。基本的に、を介して新しいコンテキストを作成してmyContext = createPackageContext("com.example.package",Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);から呼び出しますmyContext.getSharedPreferences("pref_name", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);が、外部アプリから設定に正常に書き込むことができません-(SharedPreferences.Editor).commit()はfalseを返し、logcatに編集できないという警告が表示されますpref_name.xml.bak。

アプリケーションを正常にセットアップして、両方が同じ設定ファイル(一方のデータフォルダーに保存されている)を読み書きできるようにするにはどうすればよいですか?

4

2 に答える 2

47

ファイルにプライベートモードを設定することをお勧めします。このファイルを共有するには、アプリに同じ証明書のセットで署名する必要があります。

両方のアプリで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">
....

他のパッケージからコンテキストを取得します。

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

SharedPreferenceから通常どおりアイテムを取得します。今すぐアクセスできます。

于 2014-07-15T00:14:30.497 に答える
7

まず、これは公式にはサポートされていないことに注意してください。ただし、将来Androidに追加されるサポートされている方法(つまり、この方法ではない)がある可能性があります(両方の主張のソース:このリンクの2番目の段落を参照) 。

繰り返しますが、これはサポートされておらず、不安定である可能性が非常に高いです。私は主に、それが可能かどうかを確認するための実験としてこれを行いました。このメソッドを実際にアプリケーションに組み込むことを計画している場合は、細心の注意を払ってください。

ただし、いくつかの要件が満たされている場合は、アプリケーション間で設定を共有できるようです。まず、アプリBがアプリAの設定にアクセスできるようにする場合、アプリBのパッケージ名はアプリAのパッケージ名の子である必要があります(例:アプリA:com.example.pkgアプリB:) com.example.pkg.stuff。さらに、ファイルに同時にアクセスすることはできません(アトミックアクセスを確保したい場合は、.wait( )と.notify()ですが、ここでは説明しません)。

注:これはすべて、2.2および2.3.3のエミュレーターで機能します。デバイスやAndroidのバージョン間で広範囲にテストしたことはありません。




設定を所有する予定のアプリ(上からのアプリA)で行うこと:

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ファイルをチェックするように見えます。これが、ドキュメントで複数のプロセス間で機能しないと記載されている理由です。I / Oを最小限に抑えるために、設定を取得したときに1回ロードし、アプリケーション/アクティビティを閉じたときにのみバックアップします。ただし、外部アプリケーションからこれを呼び出すと、フォルダー(最初のアプリのデータフォルダー)に対する適切なファイル権限がないという警告が表示されます。これを修正するために、自分で.bakファイルを作成し、公開して読み取り/書き込み可能にします。これを行うために選択した方法は、クラス全体で3つの変数を定義することでした。

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()の直後)で、3つの文字列のそれぞれを使用してこの関数を呼び出します。

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

これにより、ファイルがコピーされ、メインの.xmlファイルと.xml.bakファイルの両方に外部プログラムからアクセスできるようになります。また、onDestroy()でこれらの3つのメソッドを呼び出して、アプリの終了時にデータベースが適切にバックアップされていることを確認し、さらに、アプリケーションの他の場所でgetSharedPreferencesを呼び出す直前に呼び出す必要があります(そうしないと、.bakファイルが読み込まれます。別のプロセスがメインの.xmlファイルを編集している場合は、古くなっている可能性があります)。ただし、このアプリケーションで行う必要があるのはこれだけです。このアクティビティの他の場所でgetSharedPreferencesを呼び出すと、.xmlファイルからすべてのデータが取得され、getdatatype( "key")メソッドを呼び出して取得できるようになります。


アクセスファイルで行うこと(上からのアプリB)

1.)ファイルへの書き込み
これはさらに簡単です。このアクティビティにボタンを作成し、onClickメソッドにコードを設定して、共有設定ファイルに何かを保存しました。AppBのパッケージはAppAのパッケージの子である必要があることに注意してください。アプリAのコンテキストに基づいてコンテキストを作成し、そのコンテキストでgetSharedPreferencesを呼び出します。

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

これにより、他のアプリケーションで設定した文字列が取得され、このアプリケーションのテキストビューに表示されます(またはエラーメッセージが表示されます)。さらに、設定ファイルに新しい文字列を設定し、変更をコミットします。これが実行された後、他のアプリケーションがgetSharedPreferencesを呼び出すと、このアプリからの変更を含むファイルが取得されます。

于 2012-06-14T00:26:49.697 に答える