Android RIL 动态切换 4G 模块适配

简介: Android RIL 动态切换 4G 模块适配

这个补丁是我加在全志A40 4.4上面的做模块动态适配的 , 毋庸置疑 后面的Android 版本也是适用的 , 比如rockchip 也是没问题的 只是我懒得搞了而已。


调试4G模块非常简单 只是说早期模块经常切换 , 换了还得换固件 , 固件其实只是更换了so库而已。因为kernel driver 已经对vid/pid进行了适配。


这个补丁是直接在hal 层rild 做的vid/pid 然后选择so库文件的。

这个补丁主要修改了 Android RIL (Radio Interface Layer) 的部分代码,以支持动态切换不同的 3G/4G 模块。

修改的文件

  • android/hardware/ril/include/runtime/runtime.h
  • android/hardware/ril/rild/Android.mk
  • android/hardware/ril/rild/rild.c
  • android/hardware/ril/runtime-ril-port/Android.mk
  • android/hardware/ril/runtime-ril-port/runtime_port.c

文件修改说明

runtime.h

这是一个新文件,定义了一些函数和变量,用于启动 uevent 监视器,获取当前的 3G 端口设备,数据和类型。

Android.mk(在 rild 目录下)

在这个 makefile 文件中,添加了 libruntime-ril-portLOCAL_SHARED_LIBRARIES,这样 rild 就可以链接到这个新的库。

rild.c

这个文件中的修改主要是在 rild 的主函数中,添加了对 3G 模块类型的检测,并根据检测到的模块类型,动态地设置 RIL 库的路径。此外,还添加了对 uevent 的监视,当检测到 3G 模块的变化时,会重新启动 rild。

Android.mk(在 runtime-ril-port 目录下)

这是一个新文件,用于编译 runtime_port.c,生成 libruntime-ril-port 库。

runtime_port.c

这是一个新文件,实现了在 runtime.h 中定义的函数。这些函数主要用于检测当前的 3G 模块类型,以及启动对 uevent 的监视。

如何适配

  1. 将这个补丁应用到你的 Android 源码树中。
  2. 根据你的 3G 模块的特性,修改 runtime_port.c 中的 modem_3g_device_table
  3. 编译并刷入你的 Android 系统。
  4. 当你的设备启动时,rild 会自动检测当前的 3G 模块类型,并加载相应的 RIL 库。

diff --git a/android/hardware/ril/include/runtime/runtime.h b/android/hardware/ril/include/runtime/runtime.h
new file mode 100755
index 0000000000..c381b4f2f8
--- /dev/null
+++ b/android/hardware/ril/include/runtime/runtime.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
+ */
+
+#ifndef RUNTIME_H
+#define RUNTIME_H
+
+extern int start_uevent_monitor(void);
+extern const char *runtime_3g_port_device(void);
+extern const char *runtime_3g_port_data(void);
+extern int runtime_3g_port_type(void);
+enum {
+ ME909S_MODEM = 0,
+ U9300C_MODEM,
+ EC20_MODEM,
+ EM8000_MODEM,
+ UNKNOWN_MODEM,
+};
+
+extern int current_modem_type;
+
+#endif
diff --git a/android/hardware/ril/rild/Android.mk b/android/hardware/ril/rild/Android.mk
index d8ca6d368d..83c0a1a130 100755
--- a/android/hardware/ril/rild/Android.mk
+++ b/android/hardware/ril/rild/Android.mk
@@ -13,7 +13,8 @@ LOCAL_SHARED_LIBRARIES := \
  liblog \
  libcutils \
  libril \
- libdl
+ libdl  \
+ libruntime-ril-port
 
 # temporary hack for broken vendor rils
 #LOCAL_WHOLE_STATIC_LIBRARIES := \
diff --git a/android/hardware/ril/rild/rild.c b/android/hardware/ril/rild/rild.c
index 4a555f275c..e79cd3cb71 100755
--- a/android/hardware/ril/rild/rild.c
+++ b/android/hardware/ril/rild/rild.c
@@ -36,10 +36,19 @@
 #include "hardware/qemu_pipe.h"
 
 #include "radio_monitor.h"
-
+#include <runtime/runtime.h>
 #define LIB_PATH_PROPERTY   "rild.libpath"
 #define LIB_ARGS_PROPERTY   "rild.libargs"
 #define MAX_LIB_ARGS        16
+#define MAX_POLL_DEVICE_CNT 8
+
+
+
+
+#define REFERENCE_RIL_ME909S_PATH "/system/lib/libreference_me909s-ril.so"
+#define REFERENCE_RIL_U9300C_PATH "/system/lib/libreference_u9300c-ril.so"
+#define REFERENCE_RIL_EC20_PATH "/system/lib/libreference_ec20-ril.so"
+#define REFERENCE_RIL_EM8000_PATH "/system/lib/libreference_em8000-ril.so"
 
 static void usage(const char *argv0)
 {
@@ -64,6 +73,7 @@ static struct RIL_Env s_rilEnv = {
     RIL_onUnsolicitedResponse,
     RIL_requestTimedCallback
 };
+static int s_poll_device_cnt = 0;
 
 extern void RIL_startEventLoop();
 
@@ -109,44 +119,21 @@ int main(int argc, char **argv)
     char libPath[PROPERTY_VALUE_MAX];
     unsigned char hasLibArgs = 0;
     int ret = 0;
+ int modem_type = UNKNOWN_MODEM;
     int i;
  char platform[PROPERTY_VALUE_MAX] = {0};
 
  //is telephony platform?
  if(property_get("ro.sw.embeded.telephony", platform, NULL)){
    if(strcmp(platform, "true")) {
-     RLOGI("platform: wifi-only");
+     RLOGI("platform: wifi-only --1");
      radio_monitor();
    }else{
-     RLOGI("platform: telephony");
+     RLOGI("platform: telephony --2");
    }
  }
 
-#if 0
-    umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
-    for (i = 1; i < argc ;) {
-        if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {
-            rilLibPath = argv[i + 1];
-            i += 2;
-        } else if (0 == strcmp(argv[i], "--")) {
-            i++;
-            hasLibArgs = 1;
-            break;
-        } else {
-            usage(argv[0]);
-        }
-    }
 
-    if (rilLibPath == NULL) {
-        if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
-            // No lib sepcified on the command line, and nothing set in props.
-            // Assume "no-ril" case.
-            goto done;
-        } else {
-            rilLibPath = libPath;
-        }
-    }
-#else
  ret = property_get(LIB_PATH_PROPERTY, libPath, NULL);
  if (ret <= 0) {
    /* nothing to do */
@@ -174,9 +161,62 @@ int main(int argc, char **argv)
    RLOGD("err: get rilLibPath failed\n");
    goto done;
  }
+ ///$shh$20180906$add$Dynamic switching module$
+  //Wait for device ready.
+   // if (rilLibPath == NULL) {
+   while(UNKNOWN_MODEM == modem_type){
+       modem_type = runtime_3g_port_type();
+       ALOGD("111 -Couldn't find proper modem, retrying...");
+       s_poll_device_cnt++;
+       if (s_poll_device_cnt > MAX_POLL_DEVICE_CNT){
+       /*
+       *Maybe no device right now, start to monitor
+       *hotplug event later.
+       */
+       start_uevent_monitor();
+       goto done;
+       }
+       sleep(5);
+   }
+    //}
 
-#endif
-    RLOGD("\nrilLibPath = %s\n\n", rilLibPath);
+ start_uevent_monitor();
+
+    switch (modem_type){
+   case ME909S_MODEM:
+   {
+     rilLibPath = REFERENCE_RIL_ME909S_PATH;
+     break;
+   }
+   case U9300C_MODEM:
+   {
+      rilLibPath = REFERENCE_RIL_U9300C_PATH;
+      break;
+   }
+   case EC20_MODEM:
+   {
+      rilLibPath = REFERENCE_RIL_EC20_PATH;
+      break;
+   }
+   case EM8000_MODEM:
+   {
+      rilLibPath = REFERENCE_RIL_EM8000_PATH;
+      printf("");
+      break;
+   }
+
+   if (rilLibPath == NULL) {
+     if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
+       // No lib sepcified on the command line, and nothing set in props.
+       // Assume "no-ril" case.
+       goto done;
+     } else {
+       rilLibPath = libPath;
+     }
+   }
+ }
+ RLOGD("shh->rilLibPath:%s,modem_type=%d",rilLibPath,modem_type);
+ ///$shh$20180906$add$Dynamic switching module$
 
     /* special override when in the emulator */
 #if 0 //ignore this by SW
diff --git a/android/hardware/ril/runtime-ril-port/Android.mk b/android/hardware/ril/runtime-ril-port/Android.mk
new file mode 100755
index 0000000000..fdf21f4844
--- /dev/null
+++ b/android/hardware/ril/runtime-ril-port/Android.mk
@@ -0,0 +1,19 @@
+# Copyright 2006 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    runtime_port.c
+
+LOCAL_SHARED_LIBRARIES := \
+    libutils \
+    libcutils
+
+LOCAL_CFLAGS :=
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE:= libruntime-ril-port
+
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/android/hardware/ril/runtime-ril-port/runtime_port.c b/android/hardware/ril/runtime-ril-port/runtime_port.c
new file mode 100755
index 0000000000..f7682c7df1
--- /dev/null
+++ b/android/hardware/ril/runtime-ril-port/runtime_port.c
@@ -0,0 +1,452 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Copyright 2011-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#define LOG_TAG "RIL"
+#include <utils/Log.h>
+
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <linux/netlink.h>
+
+#include <signal.h>
+#include <unistd.h>
+#include <runtime/runtime.h>
+
+int current_modem_type = UNKNOWN_MODEM;
+
+#define FAKE_PORT "/dev/ttyFAKEPort"
+/* Rild need a fake port to pass continue init job,
+ * return a fake port make it runable.
+ * Or the system will enter 15s in early suspend.
+ */
+
+struct modem_3g_device {
+ const char *idVendor;
+ const char *idProduct;
+ const char *deviceport; /* sending AT command */
+ const char *dataport; /* sending 3g data */
+ const char *name;
+ const int   type;
+};
+
+#define PATH_SIZE 1024
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+static const char *USB_DIR_BASE = "/sys/bus/usb/devices/";
+
+static struct modem_3g_device modem_3g_device_table[] = {
+
+ {
+   .name           = "ME909S_MODEM",
+   .idVendor       = "12d1",
+   .idProduct      = "15c1",
+   .deviceport     = "/dev/ttyUSB0",
+   .dataport       = "/dev/ttyUSB2",
+   .type           = ME909S_MODEM,
+  },
+
+
+ {
+   .name     = "U9300C_MODEM",
+   .idVendor   = "1c9e",
+   .idProduct    = "9b3c",
+   .deviceport = "/dev/ttyUSB1",
+   .dataport   = "/dev/ttyUSB2",
+   .type     = U9300C_MODEM,
+ },
+ {
+   .name     = "EC20_MODEM",
+   .idVendor   = "2c7c",
+   .idProduct    = "0125",
+   .deviceport = "/dev/ttyUSB0",
+   .dataport   = "/dev/ttyUSB2",
+   .type     = EC20_MODEM,
+ },
+ {
+   .name   = "EM8000_MODEM",
+   .idVendor = "19d2",
+   .idProduct  = "0532",
+   .deviceport     = "/dev/ttyUSB0",
+   .dataport = "/dev/ttyUSB2",
+   .type   = EM8000_MODEM,
+ },
+};
+
+/* -------------------------------------------------------------- */
+
+#define DEBUG_UEVENT 0
+#define UEVENT_PARAMS_MAX 32
+
+enum uevent_action { action_add, action_remove, action_change };
+
+struct uevent {
+    char *path;
+    enum uevent_action action;
+    char *subsystem;
+    char *param[UEVENT_PARAMS_MAX];
+    unsigned int seqnum;
+};
+
+static void dump_uevent(struct uevent *event);
+
+int readfile(char *path, char *content, size_t size)
+{
+ int ret;
+ FILE *f;
+ f = fopen(path, "r");
+ if (f == NULL)
+   return -1;
+
+ ret = fread(content, 1, size, f);
+ fclose(f);
+ return ret;
+}
+
+int is_device_equal(struct modem_3g_device *device,
+        const char *idv, const char *idp)
+{
+ long pvid = 0xffff, ppid = 0xffff;
+ long t_vid, t_pid;
+ if (device == NULL)
+   return 0;
+ t_vid = strtol(device->idVendor, NULL, 16);
+ t_pid = strtol(device->idProduct, NULL, 16);
+ pvid = strtol(idv, NULL, 16);
+ ppid = strtol(idp, NULL, 16);
+
+ return (t_vid == pvid && t_pid == ppid);
+}
+
+struct modem_3g_device *
+find_devices_in_table(const char *idvendor, const char *idproduct)
+{
+ int i;
+ int size = ARRAY_SIZE(modem_3g_device_table);
+ struct modem_3g_device *device;
+
+ for (i = 0; i < size; i++) {
+   device = &modem_3g_device_table[i];
+
+   if (is_device_equal(device, idvendor, idproduct)) {
+     ALOGI("Runtime 3G port found matched device with "
+          "Name:%s idVendor:%s idProduct:%s",
+          device->name, device->idVendor, device->idProduct);
+
+     return device;
+   }
+ }
+
+ return NULL;
+}
+
+struct modem_3g_device *find_matched_device(void)
+{
+ struct dirent *dent;
+ DIR *usbdir;
+ struct modem_3g_device *device = NULL;
+ char *path, *path2;
+ char idvendor[64];
+ char idproduct[64];
+ int ret, i;
+
+ path = malloc(PATH_SIZE);
+    if (!path)
+        return NULL;
+
+ path2 = malloc(PATH_SIZE);
+    if (!path2) {
+        free(path);
+        return NULL;
+    }
+
+ usbdir = opendir(USB_DIR_BASE);
+ if (usbdir == NULL) {
+   free(path);
+   free(path2);
+   return NULL;
+ }
+
+ memset(path, 0, PATH_SIZE);
+ memset(path2, 0, PATH_SIZE);
+
+ while ((dent = readdir(usbdir)) != NULL) {
+   if (strcmp(dent->d_name, ".") == 0
+       || strcmp(dent->d_name, "..") == 0)
+     continue;
+   memset(idvendor, 0, sizeof(idvendor));
+   memset(idproduct, 0, sizeof(idproduct));
+   path = strcpy(path, USB_DIR_BASE);
+   path = strcat(path, dent->d_name);
+   strcpy(path2, path);
+   path = strcat(path, "/idVendor");
+   path2 = strcat(path2, "/idProduct");
+
+   ret = readfile(path, idvendor, 4);
+   if (ret <= 0)
+     continue;
+   ret = readfile(path2, idproduct, 4);
+   if (ret <= 0)
+     continue;
+   device = find_devices_in_table(idvendor, idproduct);
+   if (device != NULL)
+     goto out;
+ }
+
+ if (device == NULL)
+   ALOGI("Runtime 3G can't find supported modem");
+out:
+ closedir(usbdir);
+ free(path);
+ free(path2);
+
+ return device;
+}
+
+
+const char *runtime_3g_port_device(void)
+{
+ struct modem_3g_device *device;
+ device = find_matched_device();
+ if (device == NULL)
+   return FAKE_PORT;
+
+ /* Set gobal modem type. */
+ current_modem_type = device->type;
+
+ ALOGI("Current modem type = %d", current_modem_type);
+
+ return device->deviceport;
+}
+
+const char *runtime_3g_port_data(void)
+{
+ struct modem_3g_device *device;
+
+ device = find_matched_device();
+ if (device == NULL)
+   return FAKE_PORT;
+ return device->dataport;
+}
+
+int runtime_3g_port_type(void)
+{
+       struct modem_3g_device *device;
+       int type = UNKNOWN_MODEM;
+       if (UNKNOWN_MODEM == current_modem_type){
+               if (NULL != (device = find_matched_device())){
+                       /* Set gobal modem type. */
+                       type = device->type;
+               }
+       }else{
+               type = current_modem_type;
+       }
+
+       ALOGI("Current modem type = %d", type);
+
+       return type;
+}
+
+static void free_uevent(struct uevent *event)
+{
+    int i;
+    free(event->path);
+    free(event->subsystem);
+    for (i = 0; i < UEVENT_PARAMS_MAX; i++) {
+     if (!event->param[i])
+       break;
+     free(event->param[i]);
+    }
+    free(event);
+}
+
+static int dispatch_uevent(struct uevent *event)
+{
+ /* if it's a usb tty event in our table. make the rild reboot. */
+ int i;
+ int ret;
+ for (i = 0; i < UEVENT_PARAMS_MAX; i++) {
+   if (!event->param[i])
+     break;
+   if (strncmp(event->param[i], "PRODUCT=", 8) == 0) {
+     char vbuf[5], pbuf[5];
+     ret = sscanf(event->param[i],
+            "PRODUCT=%4s/%4s/", vbuf, pbuf);
+     if (ret < 0)
+       return -1;
+     if (find_devices_in_table(vbuf, pbuf))
+       alarm(1);
+     /* Restart in 1 second, since USB usually have
+      * many devices, this avoid rild restart too
+      * many times. */
+   }
+ }
+ return 0;
+}
+
+int process_uevent_message(int sock)
+{
+ char buffer[64 * 1024];
+ char *s = buffer, *p;
+ char *end;
+ int count, param_idx = 0, ret;
+ struct uevent *event;
+ count = recv(sock, buffer, sizeof(buffer), 0);
+ if (count < 0) {
+   ALOGE("Error receiving uevent (%s)", strerror(errno));
+   return -errno;
+ }
+ event = malloc(sizeof(struct uevent));
+ if (!event) {
+   ALOGE("Error allcating memroy (%s)", strerror(errno));
+   return -errno;
+ }
+ memset(event, 0, sizeof(struct uevent));
+
+ end = s + count;
+
+ for (p = s; *p != '@'; p++)
+   ;
+ p++;
+ event->path = strdup(p);
+ s += strlen(s) + 1;
+
+ while (s < end) {
+   if (!strncmp(s, "ACTION=", strlen("ACTION="))) {
+     char *a = s + strlen("ACTION=");
+     if (!strcmp(a, "add"))
+       event->action = action_add;
+     else if (!strcmp(a, "change"))
+       event->action = action_change;
+     else if (!strcmp(a, "remove"))
+       event->action = action_remove;
+   } else if (!strncmp(s, "SEQNUM=", strlen("SEQNUM=")))
+     event->seqnum = atoi(s + strlen("SEQNUM="));
+   else if (!strncmp(s, "SUBSYSTEM=", strlen("SUBSYSTEM=")))
+     event->subsystem = strdup(s + strlen("SUBSYSTEM="));
+   else
+     event->param[param_idx++] = strdup(s);
+   s += strlen(s) + 1;
+ }
+
+ ret = dispatch_uevent(event);
+#if DEBUG_UEVENT
+ dump_uevent(event);
+#endif
+ free_uevent(event);
+ return ret;
+}
+
+static void dump_uevent(struct uevent *event)
+{
+    int i;
+
+    ALOGD("[UEVENT] Sq: %u S: %s A: %d P: %s",
+       event->seqnum, event->subsystem, event->action, event->path);
+    for (i = 0; i < UEVENT_PARAMS_MAX; i++) {
+     if (!event->param[i])
+       break;
+     ALOGD("%s", event->param[i]);
+    }
+}
+
+void restart_rild(int p)
+{
+ ALOGI("3G Modem changed,RILD will restart...");
+ exit(-1);
+}
+
+void *usb_tty_monitor_thread(void *arg)
+{
+ struct sockaddr_nl nladdr;
+ struct pollfd pollfds[2];
+ int uevent_sock;
+ int ret, max = 0;
+ int uevent_sz = 64 * 1024;
+ int timeout = -1;
+ struct sigaction timeoutsigact;
+
+ ALOGI("3G modem monitor thread is start");
+
+ timeoutsigact.sa_handler = restart_rild;
+ sigemptyset(&timeoutsigact.sa_mask);
+ sigaddset(&timeoutsigact.sa_mask, SIGALRM);
+ sigaction(SIGALRM, &timeoutsigact, 0);
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+ nladdr.nl_pid = getpid();
+ nladdr.nl_groups = 0xffffffff;
+
+ uevent_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+ if (uevent_sock < 0) {
+   ALOGE(" Netlink socket faild, usb monitor exiting...");
+   return NULL;
+ }
+
+ if (setsockopt(uevent_sock, SOL_SOCKET, SO_RCVBUFFORCE, &uevent_sz,
+          sizeof(uevent_sz)) < 0) {
+   ALOGE("Unable to set uevent socket options: %s", strerror(errno));
+   return NULL;
+ }
+
+ if (bind(uevent_sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
+      ALOGE("Unable to bind uevent socket: %s", strerror(errno));
+      return NULL;
+ }
+ pollfds[0].fd = uevent_sock;
+ pollfds[0].events = POLLIN;
+
+ ret = fcntl(uevent_sock,F_SETFL, O_NONBLOCK);
+ if (ret < 0)
+   ALOGE("Error on fcntl:%s", strerror(errno));
+
+ while (1) {
+   ret = poll(pollfds, 1, timeout);
+
+   switch (ret) {
+   case 0:
+     ALOGD("poll timeout");
+     continue;
+   case -1:
+     ALOGD("poll error:%s", strerror(errno));
+     break;
+
+   default:
+     if (pollfds[0].revents & POLLIN)
+       process_uevent_message(uevent_sock);
+   }
+ }
+
+ close(uevent_sock);
+}
+
+int start_uevent_monitor(void)
+{
+ pthread_t pth_uevent_monitor;
+ return pthread_create(&pth_uevent_monitor, NULL,
+           usb_tty_monitor_thread, NULL);
+}
+
+


相关文章
|
29天前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
117 4
|
3月前
|
调度 Android开发 UED
Android经典实战之Android 14前台服务适配
本文介绍了在Android 14中适配前台服务的关键步骤与最佳实践,包括指定服务类型、请求权限、优化用户体验及使用WorkManager等。通过遵循这些指南,确保应用在新系统上顺畅运行并提升用户体验。
267 6
|
4月前
|
编解码 网络协议 前端开发
如何实现Android平台GB28181设备接入模块按需打开摄像头并回传数据
后台采集摄像头,如果想再进一步扩展,可以把android平台gb28181的camera2 demo,都移植过来,实现功能更强大的国标设备侧,这里主要是展示,收到国标平台侧的回传请求后,才打开摄像头,才开始编码打包,最大限度的减少资源的占用
|
4月前
|
编解码 网络协议 Android开发
Android平台GB28181设备接入模块实现后台service按需回传摄像头数据到国标平台侧
我们在做Android平台GB28181设备对接模块的时候,遇到这样的技术需求,开发者希望能以后台服务的形式运行程序,国标平台侧没有视频回传请求的时候,仅保持信令链接,有发起视频回传请求或语音广播时,打开摄像头,并实时回传音视频数据或接收处理国标平台侧发过来的语音广播数据。
|
4月前
|
Java Android开发
添加Flutter模块到已有项目(Android)
添加Flutter模块到已有项目(Android)
52 3
|
4月前
|
监控 Java 开发工具
如何快速对接Android平台GB28181接入模块(SmartGBD)
大牛直播SDK推出的Android平台GB28181接入SDK(SmartGBD),可实现不具备国标音视频能力的 Android终端,通过平台注册接入到现有的GB/T28181—2016服务,可用于如执法记录仪、智能安全帽、智能监控、智慧零售、智慧教育、远程办公、明厨亮灶、智慧交通、智慧工地、雪亮工程、平安乡村、生产运输、车载终端等场景,可能是业内为数不多功能齐全性能优异的商业级水准GB28181接入SDK。
|
5月前
|
IDE API Android开发
安卓与iOS开发环境的差异及适配策略
在移动应用开发的广阔舞台上,Android和iOS两大操作系统各据一方,各自拥有独特的开发环境和工具集。本文旨在深入探讨这两个平台在开发环境上的关键差异,并提供有效的适配策略,帮助开发者优化跨平台开发流程。通过比较Android的Java/Kotlin和iOS的Swift/Objective-C语言特性、IDE的选择、以及API和系统服务的访问方式,本文揭示了两个操作系统在开发实践中的主要分歧点,并提出了一套实用的适配方法,以期为移动开发者提供指导和启示。
|
4月前
|
编解码 开发工具 Android开发
Android平台RTMP直播推送模块技术接入说明
大牛直播SDK跨平台RTMP直播推送模块,始于2015年,支持Windows、Linux(x64_64架构|aarch64)、Android、iOS平台,支持采集推送摄像头、屏幕、麦克风、扬声器、编码前、编码后数据对接,功能强大,性能优异,配合大牛直播SDK的SmartPlayer播放器,轻松实现毫秒级的延迟体验,满足大多数行业的使用场景。RTMP直播推送模块数据源,支持编码前、编码后数据对接
|
4月前
|
监控 开发工具 Android开发
结合GB/T28181规范探讨Android平台设备接入模块心跳实现
本文介绍了GB28181标准中的状态信息报送机制,即心跳机制,用于监控设备与服务器间的连接状态。根据国标GB/T28181-2016,设备在异常时需立即发送状态信息,在正常状态下则按固定间隔(默认60秒)定期发送。若连续三次(默认值)未收到心跳,则视为离线。文章展示了在Android平台的GB28181设备接入模块(SmartGBD)中,如何调整心跳间隔为20秒及超时次数为3次,并给出了心跳消息的示例和异常处理代码片段。对于希望深入了解或遇到问题的开发者,作者提供了进一步交流的机会。
|
4月前
|
编解码 API 开发工具
Android平台轻量级RTSP服务模块二次封装版调用说明
本文介绍了Android平台上轻量级RTSP服务模块的二次封装实践,旨在简化开发流程,让开发者能更专注于业务逻辑。通过`LibPublisherWrapper`类提供的API,可在应用中轻松初始化RTSP服务、配置视频参数(如分辨率、编码类型)、启动与停止RTSP服务及流发布,并获取RTSP会话数量。此外,还展示了如何处理音频和视频数据的采集与推送。最后,文章提供了从启动服务到销毁资源的完整示例,帮助开发者快速集成实时流媒体功能。