Android的Native方式广播intent

本文是在“在Android中使用native程序(非Java)来广播intent”这篇博文的基础上的完整实现,实现了在Native下广播一个即将关机的通知。

#define LOG_TAG "IntentTest"

#include <fcntl.h>
#include <unistd.h>

#include <binder/MemoryHeapBase.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>

namespace android 
{

namespace {
    sp<IBinder>              gActivityManagerService;
    const int                kActivityManagerServicePollDelay = 500000;      // 0.5s
    const char*              kActivityManagerServiceName      = "activity";  // default name

    Mutex                    gLock;

    class DeathNotifier : public IBinder::DeathRecipient
    {
    public:
        DeathNotifier() {
        }

        virtual void binderDied(const wp<IBinder>& who) {
            ALOGV("binderDied");
            Mutex::Autolock _l(gLock);
            gActivityManagerService.clear();
            ALOGW("ActivityManager service died!");
        }
    };

    sp<DeathNotifier>         gDeathNotifier;
}; // namespace anonymous

// establish binder interface to ActivityManager service
const sp<IBinder>& getActivityManagerService()
{
	Mutex::Autolock _l(gLock);
	if (gActivityManagerService.get() == 0) {
		sp<IServiceManager> sm = defaultServiceManager();
		sp<IBinder> binder;
		do {
			binder = sm->getService(String16(kActivityManagerServiceName));
			if (binder != 0) {
				break;
			}
			ALOGW("ActivityManagerService not published, waiting...");
			usleep(kActivityManagerServicePollDelay);
		} while(true);
        if (gDeathNotifier == NULL) {
            gDeathNotifier = new DeathNotifier();
        }
        binder->linkToDeath(gDeathNotifier);
		gActivityManagerService = binder;
	}
	ALOGE_IF(gActivityManagerService == 0, "no ActivityManagerService!?");
	return gActivityManagerService;
}

// Uri.java
typedef enum URI_TYPE_ID
{
	NULL_TYPE_ID    = 0,
	StringUri       = 1,
	OpaqueUri       = 2,
	HierarchicalUri = 3,
};

// Parcel.java
typedef enum VALUE_TYPE
{
	VAL_NULL = -1,
	VAL_STRING = 0,
	VAL_INTEGER = 1,
	VAL_MAP = 2,
	VAL_BUNDLE = 3,
	VAL_PARCELABLE = 4,
	VAL_SHORT = 5,
	VAL_LONG = 6,
	VAL_FLOAT = 7,
	VAL_DOUBLE = 8,
	VAL_BOOLEAN = 9,
	VAL_CHARSEQUENCE = 10,
	VAL_LIST  = 11,
	VAL_SPARSEARRAY = 12,
	VAL_BYTEARRAY = 13,
	VAL_STRINGARRAY = 14,
	VAL_IBINDER = 15,
	VAL_PARCELABLEARRAY = 16,
	VAL_OBJECTARRAY = 17,
	VAL_INTARRAY = 18,
	VAL_LONGARRAY = 19,
	VAL_BYTE = 20,
	VAL_SERIALIZABLE = 21,
	VAL_SPARSEBOOLEANARRAY = 22,
	VAL_BOOLEANARRAY = 23,
	VAL_CHARSEQUENCEARRAY = 24,
};

// IActivityManager.java
const uint32_t BROADCAST_INTENT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 13;

void sendBroadcast(const char* action_str, const char* uri_str)
{
	Parcel data, reply;
	
	sp<IBinder> am = getActivityManagerService();
	if(am == NULL)
	{
		ALOGE("sendBroadcast(%s) get ActivityManager failed\n", String8(uri_str).string());
		return;
	}

	data.writeInterfaceToken(String16("android.app.IActivityManager"));  
	data.writeStrongBinder(NULL);             /* caller */
	/* intent */
	data.writeString16(String16(action_str)); /* action */
	if(uri_str == NULL)
	{
		data.writeInt32(NULL_TYPE_ID);
	}
	else
	{
		// only support StringUri type
		data.writeInt32(StringUri);             /* Uri - type */
		data.writeString16(String16(uri_str));  /* uri string if URI_TYPE_ID set */
	}
	data.writeString16(NULL, 0);              /* type */
	data.writeInt32(0);                       /* flags */
	data.writeString16(NULL, 0);              /* package name */
	data.writeString16(NULL, 0);              /* ComponentName */
	data.writeInt32(0);                       /* source bound - size */
	data.writeInt32(0);                       /* Categories - size */
	data.writeInt32(0);                       /* selector - size */
	data.writeInt32(0);                       /* ClipData */
	data.writeInt32(-1);                      /* bundle(extras) size */
	if(1)
	{
		data.writeInt32(0x4C444E42); // 'B' 'N' 'D' 'L'
		int oldPos = data.dataPosition();
		{ /* writeMapInternal */
			data.writeInt32(1); /* size */
			data.writeInt32(VAL_STRING);
			data.writeString16(String16("status"));
			data.writeInt32(VAL_STRING);
			data.writeString16(String16("OFF"));
		}
		int newPos = data.dataPosition();
		data.setDataPosition(oldPos - 8);
		data.writeInt32(newPos - oldPos); /* length */
		data.setDataPosition(newPos);
	}
	/* end of intent */
	data.writeString16(NULL, 0);  /* resolvedType */
	data.writeStrongBinder(NULL); /* resultTo */
	data.writeInt32(-1);          /* result code */
	data.writeString16(NULL, 0);  /* result data */
	data.writeInt32(-1);          /* no result extra */
	data.writeString16(NULL, 0);  /* permission */
	data.writeInt32(false);       /* app operation in AppOpsManager */
	data.writeInt32(false);       /* serialized */
	data.writeInt32(false);       /* sticky */
	data.writeInt32(false);       /* userid */
	
	status_t ret = am->transact(BROADCAST_INTENT_TRANSACTION, data, &reply);
	if (ret == NO_ERROR)
	{
		int32_t exceptionCode = reply.readExceptionCode();
		if (!exceptionCode)
		{
			ALOGD("sendBroadcast(%s) succeed\n", String8(action_str).string());
		} 
		else
		{
			// An exception was thrown back; fall through to return failure
			ALOGE("sendBroadcast(%s) caught exception %d\n", String8(action_str).string(), exceptionCode);
		}
	}
}

// Intent.java
const char ACTION_POWER_DOWN_NOW[] = "android.intent.action.POWER_DOWN_NOW";

};

using namespace android;

int main(int argc, char **argv)
{
	android::ProcessState::self()->startThreadPool();
	
	int i;
	status_t status;
	
	printf("IntentTest start\n");
	
	sendBroadcast(ACTION_POWER_DOWN_NOW, NULL);
	
	printf("IntentTest stop\n");  
	
	return 0;
}

对应的java代码形如:

Intent intent = new Intent(ACTION_POWER_DOWN_NOW);
intent.putExtra("status", "OFF");
mContext.sendBroadcast(intent);



  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值