如何在不同的Android应用程序之间双向传递数据?

8
什么是将字符串变量从一个应用程序传递到另一个应用程序并返回值的最简单方法?我可以访问两个应用程序的源代码,但它必须是两个不同的应用程序。
我尝试使用startActivityForResult,但这似乎仅在同一应用程序的活动之间起作用。当从不同包中调用活动时,startActivityForResult立即返回RESULT_CANCELED。似乎有可能通过服务解决这个问题,但对于只有一些字符串变量来说,这是否有点过度了呢?
有没有一种简单而干净的方法来做到这一点?
以下是我尝试使用startActivityForResult的代码:
//App A:
            Intent intent = new Intent();
            intent.setAction("com.example.testapp.MESSAGE");
            Bundle b = new Bundle();
            b.putString("loginToken", "263bhqw3jhf6as4yf8j0agtz8h2hj2z9j3hg3g3ggh34uzh2h2ui78h3i9wdnj89x");
            intent.putExtra("MyData", b);

            startActivityForResult(intent, TEST_REQUEST);

    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d("pairing", "onActivityResult called");
    // Check which request we're responding to
    if (requestCode == TEST_REQUEST) {
        // Make sure the request was successful
        Log.d("pairing", "got result, resultCode: " + resultCode);
        if (resultCode == RESULT_OK) {
            // The Intent's data Uri identifies which contact was selected.
            if (data.hasExtra("returnMessage")) {
                Toast.makeText(this, data.getExtras().getString("returnMessage"), Toast.LENGTH_LONG).show();
            }

        }
    }
}


            // App B:
        Intent result = new Intent();
        Bundle b = new Bundle();
        b.putString("returnValue", "this is the returned value");
        result.putExtra("MyData", b);
        setResult(Activity.RESULT_OK, result);
        Log.d("pairing", "RESULT_OK set");
        finish();


//App B Manifest
        <activity
        android:name="com.example.testapp"
        android:launchMode="singleTop"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustPan" >
        <intent-filter>
            <action android:name="com.example.testapp.MESSAGE" />

            <category android:name="android.intent.category.DEFAULT" />

            <data android:mimeType="text/plain" />
        </intent-filter></activity>

有人发现错误了吗?应用程序B总是立即返回RESULT_CANCELED

编辑: 现在我得到一个android.content.activitynotfoundexception错误,没有找到处理意图{act=com.example.testapp.MESSAGE(有额外信息)}的活动。我做错了什么?


1
你可以发布这两个活动的代码吗? - Ariel Magbanua
startActivityForResult 应该可以工作...问题似乎在你的代码中。 - Selvin
对我来说,使用startActivityForResult()似乎不可能。它可以在同一应用程序的活动之间工作,即使使用不同的包,但不能在两个不同的应用程序之间工作。请参见链接 - qefzec
从清单中删除<data android:mimeType="text/plain" />部分。 - Selvin
6个回答

2

1

对我来说,需要设置 ContentProvider 来返回两个或三个字符串似乎有点令人沮丧。不过,这似乎是最优雅的解决方案。 - qefzec
这只是一个建议的方式,你也可以尝试其他答案。SharedPreference 也是一种不错的方式。它取决于你的需求以及你将如何使用。谢谢。 - Ranjit

0

我有两个应用程序,可以相互传递数据。

App1...
Intent i = new Intent("com.xxx.yyy.MESSAGE");
Bundle b = new Bundle();
b.putString("AAA", getAAA());
i.putExtra("MyData", b);
startActivityForResult(i, "myProcess");

没什么花哨的东西...

App2...在onResume()中...

 Intent i = getIntent();
 if (i != null && i.getAction().equals("com.xxx.yyy.MESSAGE") {
    ...get the data from the bundle
 }

请注意,AndroidManifest.xml(适用于App2)中有一个活动的以下条目。
 <intent-filter>
    <action android:name="com.xxx.yyy.MESSAGE"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:mimeType="text/plain"/>
 </intent-filter>

app1和app2不在同一个包中吗?我尝试了你的方法,但对我没有用。我将提供我的代码。 - qefzec
在App2的onFinish()方法中,我创建了另一个Intent,其中包含我要传递回去的数据。为了返回到调用的应用程序(App1),我会调用setResult(RESULT_OK, returnIntent);,当然,如果遇到错误,我会使用setResult(RESULT_CANCELED);返回到App1。 - David M
我不确定我做错了什么...你能提供所有相关的清单摘录吗?我真的很想知道我做错了什么... - qefzec
抱歉,我的开发机器没有连接到网络...你设置了返回代码吗?例如 setResult(RESULT_OK, returnIntent);?如果你不设置的话,我不确定默认值是什么。 - David M
另外,我的代码与你的代码的一个小差别是,在设置返回码后,你调用了 finish();。我已经重写了 finish()...在那里设置了返回码...然后调用了 super.finish(); 不知道这是否有所不同。 - David M
显示剩余3条评论

0

您可以在属于这些应用程序的两个服务之间交换信使(即使这些应用程序来自两个不同的包),并使用这些信使进行通信。


0

SharedPreferences 可能会在这方面对你有所帮助。


哦,这样传递数据(无需存储)是否是一种简洁的方式呢?所以只需在一个应用程序中声明一个SharedPreference,并将其用于两个应用程序? - qefzec
如果您使用SharedPreferences,数据将在本地进行存储。对于任何特定的偏好设置,都有一个所有客户端共享的此类的单个实例。因此,一旦修改,修改后的值就会反映在所有地方。这是访问数据的方式。我更喜欢这种方式而不是数据传递(使用intent、putExtra等)。 - Sash_KP

0
public class MyParcelable implements Parcelable {
    // You can include parcel data types
    private int mData;
    private String mName;

    // We can also include child Parcelable objects. Assume MySubParcel is such a Parcelable:
    private MySubParcelable mInfo;

    // This is where you write the values you want to save to the `Parcel`.  
    // The `Parcel` class has methods defined to help you save all of your values.  
    // Note that there are only methods defined for simple values, lists, and other Parcelable objects.  
    // You may need to make several classes Parcelable to send the data you want.
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mData);
        out.writeString(mName);
        out.writeParcelable(mInfo, flags)
    }

    // Using the `in` variable, we can retrieve the values that 
    // we originally wrote into the `Parcel`.  This constructor is usually 
    // private so that only the `CREATOR` field can access.
    private MyParcelable(Parcel in) {
        mData = in.readInt();
        mName = in.readString();
        mInfo = in.readParcelable(MySubParcelable.class.getClassLoader());
    }

    public MyParcelable() {
        // Normal actions performed by class, since this is still a normal object!
    }

    // In the vast majority of cases you can simply return 0 for this.  
    // There are cases where you need to use the constant `CONTENTS_FILE_DESCRIPTOR`
    // But this is out of scope of this tutorial
    @Override
    public int describeContents() {
        return 0;
    }

    // After implementing the `Parcelable` interface, we need to create the 
    // `Parcelable.Creator<MyParcelable> CREATOR` constant for our class; 
    // Notice how it has our class specified as its type.  
    public static final Parcelable.Creator<MyParcelable> CREATOR
            = new Parcelable.Creator<MyParcelable>() {

        // This simply calls our new constructor (typically private) and 
        // passes along the unmarshalled `Parcel`, and then returns the new object!
        @Override
        public MyParcelable createFromParcel(Parcel in) {
            return new MyParcelable(in);
        }

        // We just need to copy this and change the type to match our class.
        @Override
        public MyParcelable[] newArray(int size) {
            return new MyParcelable[size];
        }
    };
}

在此处阅读


问题非常清晰。如何在两个不同的应用程序之间传递数据。您的情况将适用于两个不同的活动。 - vgokul129

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接