Android的Native方式广播intent
16lz
2021-01-26
本文是在“在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 serviceconst 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.javatypedef enum URI_TYPE_ID{NULL_TYPE_ID = 0,StringUri = 1,OpaqueUri = 2,HierarchicalUri = 3,};// Parcel.javatypedef 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.javaconst 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 typedata.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 failureALOGE("sendBroadcast(%s) caught exception %d\n", String8(action_str).string(), exceptionCode);}}}// Intent.javaconst 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);
更多相关文章
- Android(安卓)8.1静态广播的使用以及添加权限
- android 8.0 ,9.0 静态广播不显示问题处理
- android广播的使用
- Android拨号键盘增加魔力爱心数字
- [置顶] ANDROID 返回,菜单和HOME键的监听
- Android使用自定义view在指定时间内匀速画一条直线的实例代码
- Android(安卓)BroadcastRecevicer广播分类
- android关于AndroidManifest.xml详细分析
- android中检测网络是否断开