android - 使用 Binder 从 native cpp 应用程序中 bundle Intent

标签 android c++ android-intent android-binder

我正在尝试从 native cpp 代码调用 Intent 。 基本上,据我所知,我必须编写一个 Parcel 来匹配来自 frameworks/base/core/java/android/app/ActivityManagerNative.java 的确切反序列化序列;案例 BROADCAST_INTENT_TRANSACTION。

到目前为止的进展是,我已经在 J​​ava 应用程序中收到了 Intent ,但我在 bundle 负载方面遇到了一些问题。我已经调试了 Java 应用程序,它似乎将垃圾读取为 int,而不是读取保存包键类型的 int。

W/System.err( 1386): java.lang.RuntimeException: Parcel android.os.Parcel@71aa5c5: Unmarshalling unknown type code 6815843 at offset 12
W/System.err( 1386):    at android.os.Parcel.readValue(Parcel.java:2228)
W/System.err( 1386):    at android.os.Parcel.readArrayMapInternal(Parcel.java:2485)
W/System.err( 1386):    at android.os.BaseBundle.unparcel(BaseBundle.java:221

这里是使用的原生代码

#include <unistd.h>
#include <binder/IBinder.h>
#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <assert.h>

namespace android {

static const int BROADCAST_INTENT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 13;

int send_intent()
{
    int NULL_TYPE_ID = 0;

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> am = sm->checkService(String16("activity"));
    assert(am != NULL);

    Parcel data, reply;
    data.writeInterfaceToken(String16("android.app.IActivityManager"));
    data.writeStrongBinder(NULL);

    /*intent*/

    data.writeString16(String16("com.etc.etc.receiver")); /* action */

    data.writeInt32(NULL_TYPE_ID); /* mData */
    data.writeString16(NULL, 0); /* type */
    data.writeInt32(0); /* flags */
    data.writeString16(NULL, 0); /* package name  */
    data.writeString16(NULL, 0); /* ComponentName - class */

    data.writeInt32(0); /*  no source bounds */
    data.writeInt32(0); /* no categories  */

    /* skip categories */

    data.writeInt32(0); /* no selector  */
    data.writeInt32(0); /* no clip data  */
    data.writeInt32(0); /* content user hint */


    { /* Extras Bundle */
        data.writeInt32(0); /* dummy, will hold length */

        data.writeInt32(0x4C444E42); // 'B' 'N' 'D' 'L'
        int oldPos = data.dataPosition();
        { /* writeMapInternal */
            data.writeInt32(2); /* writeMapInternal - size in pairs */

            data.writeInt32(VAL_STRING); /* type for key */
            data.writeString16(String16("first")); /* key */
            data.writeInt32(VAL_INTEGER); /* type for value */
            data.writeInt32(1337); /* value */

            data.writeInt32(VAL_STRING); /* type for key */
            data.writeString16(String16("second")); /* key */
            data.writeInt32(VAL_INTEGER);   /* type for value */
            data.writeInt32(1338); /* value */


        }
        int newPos = data.dataPosition();
        data.setDataPosition(oldPos - 8); /* eight bytes: size integer + bundle integer  */
        int difference = newPos - oldPos;
        data.writeInt32(difference); /* total length of the bundle */

        data.setDataPosition(newPos);
    }

    data.writeString16(NULL, 0); /* resolvedType */
    data.writeStrongBinder(NULL); /* resultTo */
    data.writeInt32(-1);          /* resultCode */
    data.writeString16(NULL, 0);  /* resultData */
    data.writeInt32(-1);        /* result extras */

    data.writeString16(NULL, 0);  /* grant all permissions */
    data.writeInt32(0); /* appOp */
    data.writeInt32(0); /* serialized */
    data.writeInt32(0); /* sticky */
    data.writeInt32(0); /* userid */

    status_t ret = am->transact(BROADCAST_INTENT_TRANSACTION, data, &reply);

    if (ret == NO_ERROR)
    {
        int32_t exceptionCode = reply.readExceptionCode();
        if (!exceptionCode)
        {
            ALOGD("sendBroadcast succeed\n");
        }
        else
        {
            // An exception was thrown back; fall through to return failure
            ALOGE("sendBroadcastcaught exception %d\n", exceptionCode);
        }
    }
    else
    {
        ALOGD("am->transact returned: %d", ret);
    }

    return 0;
}
};

最佳答案

删除下面的代码:

data.writeInt32(VAL_STRING); /* type for key */

不需要 key 类型,因为它始终是一个字符串。此字段未编码,则不要解编。

关于android - 使用 Binder 从 native cpp 应用程序中 bundle Intent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37300703/

相关文章:

c++ - 如何限制同一文件中的函数范围,因为它是在 C++ 中定义的?

java - Intent.putExtras 大小限制?

Android 以 Intent.ACTION_INSTALL_PACKAGE 开始一个 Activity 并且不返回额外的返回结果

android - 如何设置edittext以显示搜索按钮或键盘上的输入按钮?

java - 在 ListView 中获取项目位置然后使用 if/else 子句或 switch 语句

c++ - 使用 ShellExecute 打开不带 ".exe"扩展名的可执行文件

C++ 段错误 -tinyXML

java - 我怎样才能在Android java中 "kill"Intent

android - Android MVP 中的 Firebase 远程配置单元测试?

php - 使用 PHP openssl 进行应用内购买签名验证