Android Mediatek 禁用 USB 权限请求和声音提示 & 解决USB HID设备不识别问题(附带USB调试过程)

简介: Android Mediatek 禁用 USB 权限请求和声音提示 & 解决USB HID设备不识别问题(附带USB调试过程)

这个 修改主要在 Android 系统中修改了 USB 权限请求和声音提示的相关代码,使得在插入 USB 设备时,系统不再弹出权限请求对话框,并且不再播放声音提示。

修改的文件:

  1. frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
  2. frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
  3. frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java
  4. frameworks/base/services/usb/java/com/android/server/usb/UsbSettingsManager.java

文件修改说明:

  1. UsbPermissionActivity.java: 在 UsbPermissionActivity 类中,禁用了 setupAlert 方法,并将 mPermissionGranted 设置为 true,使得在插入 USB 设备时,系统不再弹出权限请求对话框。
  2. NotificationManagerService.java: 在 NotificationManagerService 类中,禁用了播放声音提示的相关代码,使得在插入 USB 设备时,系统不再播放声音提示。
  3. UsbHostManager.java: 在 UsbHostManager 类中,添加了 mNewConfigurationmNewInterface 的初始化代码。
  4. UsbSettingsManager.java: 在 UsbSettingsManager 类中,修改了 hasPermissioncheckPermission 方法,使得这些方法总是返回 true,即系统总是认为已经获得了 USB 设备的权限。
 
---
 .../systemui/usb/UsbPermissionActivity.java        |  4 +++-
 .../notification/NotificationManagerService.java   |  6 ++++--
 .../com/android/server/usb/UsbHostManager.java     |  3 +++
 .../com/android/server/usb/UsbSettingsManager.java | 23 +++++++++++++---------
 4 files changed, 24 insertions(+), 12 deletions(-)
 mode change 100644 => 100755 frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
 
diff --git a/frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index 1e69fc5..e0bb559 100755
--- a/frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -110,7 +110,9 @@ public class UsbPermissionActivity extends AlertActivity
                                                     com.android.internal.R.id.clearDefaultHint);
         mClearDefaultHint.setVisibility(View.GONE);
 
-        setupAlert();
+        //setupAlert();
+       mPermissionGranted = true;
+       finish();
 
     }
 
diff --git a/frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java b/frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
old mode 100644
new mode 100755
index 9b24172..e01699d
--- a/frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2230,12 +2230,14 @@ public class NotificationManagerService extends SystemService {
                         AudioAttributes.toLegacyStreamType(audioAttributes)) != 0)
                             && !mAudioManager.isAudioFocusExclusive()) {
                     final long identity = Binder.clearCallingIdentity();
-                    try {
+         //modify disabled usb plug in sound playing 220322
+                    /*try {
                         final IRingtonePlayer player =
                                 mAudioManager.getRingtonePlayer();
                         if (player != null) {
                             if (DBG) Slog.v(TAG, "Playing sound " + soundUri
                                     + " with attributes " + audioAttributes);
+             
                             player.playAsync(soundUri, record.sbn.getUser(), looping,
                                 audioAttributes);
                             buzzBeepBlinked = true;
@@ -2243,7 +2245,7 @@ public class NotificationManagerService extends SystemService {
                     } catch (RemoteException e) {
                     } finally {
                         Binder.restoreCallingIdentity(identity);
-                    }
+                    }*/
                 }
             }
 
diff --git a/frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java b/frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java
index e769bda..088fece 100644
--- a/frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -230,6 +230,9 @@ public class UsbHostManager {
             mNewConfigurations = null;
             mNewInterfaces = null;
             mNewEndpoints = null;
+     //这里是新加的代码
+            mNewConfiguration = null;
+            mNewInterface = null;
         }
     }
 
diff --git a/frameworks/base/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/frameworks/base/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index 37b5c51..2ccbbac 100644
--- a/frameworks/base/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/frameworks/base/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -981,7 +981,7 @@ class UsbSettingsManager {
     }
 
     public boolean hasPermission(UsbDevice device) {
-        synchronized (mLock) {
+    /*    synchronized (mLock) {
             int uid = Binder.getCallingUid();
             if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
                 return true;
@@ -992,10 +992,12 @@ class UsbSettingsManager {
             }
             return uidList.get(uid);
         }
+*/
+ return true;
     }
 
     public boolean hasPermission(UsbAccessory accessory) {
-        synchronized (mLock) {
+        /*synchronized (mLock) {
             int uid = Binder.getCallingUid();
             if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
                 return true;
@@ -1005,19 +1007,20 @@ class UsbSettingsManager {
                 return false;
             }
             return uidList.get(uid);
-        }
+        }*/
+ return true;
     }
 
     public void checkPermission(UsbDevice device) {
-        if (!hasPermission(device)) {
+    /*    if (!hasPermission(device)) {
             throw new SecurityException("User has not given permission to device " + device);
-        }
+        }*/
     }
 
     public void checkPermission(UsbAccessory accessory) {
-        if (!hasPermission(accessory)) {
+      /*  if (!hasPermission(accessory)) {
             throw new SecurityException("User has not given permission to accessory " + accessory);
-        }
+        }*/
     }
 
     private void requestPermissionDialog(Intent intent, String packageName, PendingIntent pi) {
@@ -1054,7 +1057,8 @@ class UsbSettingsManager {
       Intent intent = new Intent();
 
         // respond immediately if permission has already been granted
-      if (hasPermission(device)) {
+      //if (hasPermission(device)) {
+      if (true) {
             intent.putExtra(UsbManager.EXTRA_DEVICE, device);
             intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
             try {
@@ -1074,7 +1078,8 @@ class UsbSettingsManager {
         Intent intent = new Intent();
 
         // respond immediately if permission has already been granted
-        if (hasPermission(accessory)) {
+        //if (hasPermission(accessory)) {
+        if (true) {
             intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
             intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
             try {
-- 
1.9.1
  1. 调试阶段:问题调试
插着HIDPOS开机
 
 
-----------开机上电usb只有以下3个
Bus 001 Device 005: ID 1a40:0201
Bus 001 Device 001: ID 1d6b:0002
Bus 001 Device 006: ID 26f1:8803
 
-----------重新拔插一下USB变成了4个
Bus 001 Device 005: ID 1a40:0201
Bus 001 Device 001: ID 1d6b:0002
Bus 001 Device 008: ID 26f1:8803
Bus 001 Device 007: ID 1c4f:0034
 
 
----不能识别设备
UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=3,mSubclass=1,mProtocol=2,mEndpoints=[
----可以识别设备
UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=3,mSubclass=0,mProtocol=0,mEndpoints=[
 
 
----拔插鼠标
727-911/system_process D/UsbHostManager: Added device UsbDevice[mName=/dev/bus/usb/001/004,mVendorId=7247,mProductId=52,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=SIGMACHIP,mProductName=Usb Mouse,mSerialNumber=null,mConfigurations=[
    UsbConfiguration[mId=1,mName=null,mAttributes=160,mMaxPower=50,mInterfaces=[
    UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=3,mSubclass=1,mProtocol=2,mEndpoints=[
    UsbEndpoint[mAddress=129,mAttributes=3,mMaxPacketSize=4,mInterval=10]]]]
 
 
----拔插HID POS
 727-911/system_process D/UsbHostManager: Added device UsbDevice[mName=/dev/bus/usb/001/005,mVendorId=9969,mProductId=34819,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=TMS,mProductName=HIDPOS,mSerialNumber=1234567890abcd,mConfigurations=[
    UsbConfiguration[mId=1,mName=null,mAttributes=224,mMaxPower=50,mInterfaces=[
    UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=3,mSubclass=0,mProtocol=0,mEndpoints=[
    UsbEndpoint[mAddress=130,mAttributes=3,mMaxPacketSize=64,mInterval=4]
    UsbEndpoint[mAddress=1,mAttributes=3,mMaxPacketSize=64,mInterval=1]]]]
 
 
 
67:01000010
 
 
 
 
  USB Host State:
    /dev/bus/usb/001/014: UsbDevice[mName=/dev/bus/usb/001/014,mVendorId=7247,mProductId=52,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=SIGMACHIP,mProductName=Usb Mouse,mSerialNumber=null,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=160,mMaxPower=50,mInterfaces=[
UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=3,mSubclass=1,mProtocol=2,mEndpoints=[
UsbEndpoint[mAddress=129,mAttributes=3,mMaxPacketSize=4,mInterval=10]]]]
    /dev/bus/usb/001/013: UsbDevice[mName=/dev/bus/usb/001/013,mVendorId=6127,mProductId=24600,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=Lite-On Technology Corp.,mProductName=Lenovo USB Keyboard,mSerialNumber=null,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=160,mMaxPower=50,mInterfaces=[]]
 
 
 
  USB Host State:
    /dev/bus/usb/001/015: UsbDevice[mName=/dev/bus/usb/001/015,mVendorId=6127,mProductId=24600,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=Lite-On Technology Corp.,mProductName=Lenovo USB Keyboard,mSerialNumber=null,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=160,mMaxPower=50,mInterfaces=[
UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=3,mSubclass=1,mProtocol=1,mEndpoints=[
UsbEndpoint[mAddress=129,mAttributes=3,mMaxPacketSize=8,mInterval=10]]
UsbInterface[mId=1,mAlternateSetting=0,mName=null,mClass=3,mSubclass=0,mProtocol=0,mEndpoints=[
UsbEndpoint[mAddress=130,mAttributes=3,mMaxPacketSize=3,mInterval=10]]]]
    /dev/bus/usb/001/014: UsbDevice[mName=/dev/bus/usb/001/014,mVendorId=7247,mProductId=52,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=SIGMACHIP,mProductName=Usb Mouse,mSerialNumber=null,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=160,mMaxPower=50,mInterfaces=[]]
 
 
 
 
 
  USB Host State:
    /dev/bus/usb/001/016: UsbDevice[mName=/dev/bus/usb/001/016,mVendorId=7247,mProductId=52,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=SIGMACHIP,mProductName=Usb Mouse,mSerialNumber=null,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=160,mMaxPower=50,mInterfaces=[
UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=3,mSubclass=1,mProtocol=2,mEndpoints=[
UsbEndpoint[mAddress=129,mAttributes=3,mMaxPacketSize=4,mInterval=10]]]]
    /dev/bus/usb/001/015: UsbDevice[mName=/dev/bus/usb/001/015,mVendorId=6127,mProductId=24600,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=Lite-On Technology Corp.,mProductName=Lenovo USB Keyboard,mSerialNumber=null,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=160,mMaxPower=50,mInterfaces=[]]
 
 
  USB Host State:
    /dev/bus/usb/001/016: UsbDevice[mName=/dev/bus/usb/001/016,mVendorId=7247,mProductId=52,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=SIGMACHIP,mProductName=Usb Mouse,mSerialNumber=null,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=160,mMaxPower=50,mInterfaces=[]]
    /dev/bus/usb/001/017: UsbDevice[mName=/dev/bus/usb/001/017,mVendorId=6127,mProductId=24600,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=Lite-On Technology Corp.,mProductName=Lenovo USB Keyboard,mSerialNumber=null,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=160,mMaxPower=50,mInterfaces=[
UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=3,mSubclass=1,mProtocol=1,mEndpoints=[
UsbEndpoint[mAddress=129,mAttributes=3,mMaxPacketSize=8,mInterval=10]]
UsbInterface[mId=1,mAlternateSetting=0,mName=null,mClass=3,mSubclass=0,mProtocol=0,mEndpoints=[
UsbEndpoint[mAddress=130,mAttributes=3,mMaxPacketSize=3,mInterval=10]]]]
 
 
  1. 调试阶段:问题验证
 
复现方式:
  通过先后拔插USB调试打印中,发现dumpsys usb , hid pos 没有UsbInterface会导致APP端的usb 通讯流程失败。 
 
问题原因:
  Android 系统 usb host manger 会将第一个USB设备的UsbInterface对象替换,所以当有两台USB设备链接时,始终都
  会有一台USB设备无法与之通信。
 
解决办法:
  将mNewConfiguration对象,mNewInterface对象都置位空,这样在第二个USB设备初始化时,mNewConfiguration就
  保持为空的状态,不会进行二次赋值。
 
gpio修改的弊端:
  拔插usb iddig, hid pos 概率性能出现UsbInterface,却决于usb加载顺序。
 
 
修改过后的打印:
USB Host State:
    /dev/bus/usb/001/009: UsbDevice[mName=/dev/bus/usb/001/009,mVendorId=7247,mProductId=52,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=SIGMACHIP,mProductName=Usb Mouse,mSerialNumber=null,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=160,mMaxPower=50,mInterfaces=[
>>>>>UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=3,mSubclass=1,mProtocol=2,mEndpoints=[
UsbEndpoint[mAddress=129,mAttributes=3,mMaxPacketSize=4,mInterval=10]]]]
    /dev/bus/usb/001/008: UsbDevice[mName=/dev/bus/usb/001/008,mVendorId=9969,mProductId=34819,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=TMS,mProductName=HIDPOS,mSerialNumber=1234567890abcd,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=224,mMaxPower=50,mInterfaces=[
    //正确打印会出现
>>>>>UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=3,mSubclass=0,mProtocol=0,mEndpoints=[
UsbEndpoint[mAddress=130,mAttributes=3,mMaxPacketSize=64,mInterval=4]
UsbEndpoint[mAddress=1,mAttributes=3,mMaxPacketSize=64,mInterval=1]]]]
 
  1. 调试阶段:APP端USB调试函数
    public void usbPrint() {
 
        // 取连接到设备上的USB设备集合
        usbManager = (UsbManager) activity.getSystemService(Context.USB_SERVICE);
        HashMap<String, UsbDevice> map = usbManager.getDeviceList();
        // 没有连接设备
        if (map.isEmpty()) {
//            ToastUtil.showToast(activity, activity.getString(R.string.connect_usb));
            return;
        }
        // 遍历集合取指定的USB设备
        UsbDevice usbDevice = null;
        for (UsbDevice device : map.values()) {
            int VendorID = device.getVendorId();
            int ProductID = device.getProductId();
            if (VendorID == 9969 && ProductID == 34819) {
                usbDevice = device;
                break;
            }
        }
        // 没有找到设备
        if (usbDevice == null) return;
        Log.d(TAG, "print usb device 22:" + usbDevice);
        // 程序是否有操作设备的权限
        if (!usbManager.hasPermission(usbDevice)) {
            usbManager.requestPermission(usbDevice, mPermissionIntent);
            return;
        }
        Log.d(TAG, "print usb device 33:" + usbDevice.getInterfaceCount());
       // ShellUtils.execCommand("echo \"-w=67:0 1 0 0 0 1 0\" >/sys/devices/virtual/misc/mtgpio/pin", true);
 
        if (usbDevice.getInterfaceCount() == 0) {
            //ShellUtils.execCommand("echo \"-w=67:0 1 1 0 1 1 0\" >/sys/devices/virtual/misc/mtgpio/pin",false);
        }
        // 设备接口, 注意设备不同接口不同, 这里取第一个
        UsbInterface usbInterface = usbDevice.getInterface(0);
        Log.d(TAG, "print usb device 44:" + usbInterface);
        // 分配端点, 注意设备不同端点不同, 这里取第一个
        outEndpoint = usbInterface.getEndpoint(0);
        Log.d(TAG, "print usb device 55:" + outEndpoint);
        // 打开设备建立连接
        connection = usbManager.openDevice(usbDevice);
        connection.claimInterface(usbInterface, true);
    }


目录
打赏
0
0
0
0
75
分享
相关文章
|
3月前
|
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
120 11
"解锁Android权限迷宫:一场惊心动魄的动态权限请求之旅,让你的应用从平凡跃升至用户心尖的宠儿!"
随着Android系统的更新,权限管理成为应用开发的关键。尤其在Android 6.0(API 级别 23)后,动态权限请求机制的引入提升了用户隐私保护,要求开发者进行更精细的权限管理。
101 2
基于Amlogic 安卓9.0, 驱动简说(四):Platform平台驱动,驱动与设备的分离
本文介绍了如何在基于Amlogic T972的Android 9.0系统上使用Platform平台驱动框架和设备树(DTS),实现设备与驱动的分离,并通过静态枚举在设备树中描述设备,自动触发驱动程序的加载和设备创建。
145 0
基于Amlogic 安卓9.0, 驱动简说(四):Platform平台驱动,驱动与设备的分离
基于Amlogic 安卓9.0, 驱动简说(二):字符设备驱动,自动创建设备
这篇文章是关于如何在基于Amlogic T972的Android 9.0系统上,通过自动分配设备号和自动创建设备节点文件的方式,开发字符设备驱动程序的教程。
130 0
基于Amlogic 安卓9.0, 驱动简说(二):字符设备驱动,自动创建设备
基于Amlogic 安卓9.0, 驱动简说(一):字符设备驱动,手动创建设备
本文是关于在Amlogic安卓9.0平台上创建字符设备驱动的教程,详细介绍了驱动程序的编写、编译、部署和测试过程,并提供了完整的源码和应用层调用示例。
169 0
基于Amlogic 安卓9.0, 驱动简说(一):字符设备驱动,手动创建设备
Android平台RTMP推送|轻量级RTSP服务如何实现麦克风|扬声器声音采集切换
Android平台扬声器播放声音的采集,在无纸化同屏等场景下,意义很大,早期低版本的Android设备,是没法直接采集扬声器audio的(从Android 10开始支持),所以,如果需要采集扬声器audio,需要先做系统版本判断,添加相应的权限。
137 0
|
10月前
|
Android系统 文件访问权限笔记
Android系统 文件访问权限笔记
800 1
Android 7.0之访问文件的权限和FileProvider类
转载请标明出处: http://blog.csdn.net/djy1992/article/details/72533310 本文出自:【奥特曼超人的博客】 权限更改 Android 7.0 做了一些权限更改,这些更改可能会影响您的应用。
3741 0
【Android 性能优化】应用启动优化 ( 方法追踪代码模板 | 示例项目 | SD 卡访问权限 | 示例代码 | 获取 Trace 文件 | Android Studio 查看文件)
【Android 性能优化】应用启动优化 ( 方法追踪代码模板 | 示例项目 | SD 卡访问权限 | 示例代码 | 获取 Trace 文件 | Android Studio 查看文件)
241 0
【Android 性能优化】应用启动优化 ( 方法追踪代码模板 | 示例项目 | SD 卡访问权限 | 示例代码 | 获取 Trace 文件 | Android Studio 查看文件)

热门文章

最新文章

  • 1
    Android历史版本与APK文件结构
    13
  • 2
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    20
  • 3
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
    10
  • 4
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    4
  • 5
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    2
  • 6
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    7
  • 7
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
    4
  • 8
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    2
  • 9
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
    10
  • 10
    Android实战经验之Kotlin中快速实现MVI架构
    12
  • 1
    android FragmentManager 删除所有Fragment 重建
    18
  • 2
    Android实战经验之Kotlin中快速实现MVI架构
    36
  • 3
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
    36
  • 4
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
    43
  • 5
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    149
  • 6
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    47
  • 7
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    59
  • 8
    Android历史版本与APK文件结构
    165
  • 9
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    48
  • 10
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    42
  • AI助理

    你好,我是AI助理

    可以解答问题、推荐解决方案等