導航:首頁 > 操作系統 > hidapiandroid

hidapiandroid

發布時間:2022-09-08 05:03:41

① 各位大神們,速來。。 小弟用android官方的api能夠對U盤等存儲設備進行識別,但是對於hid的設備卻不能識別

可能是驅動問題

② Android之隱藏api介紹

..

Android P 引入了針對非 SDK 介面(俗稱為隱藏API)的使用限制。這是繼 Android N上針對 NDK 中私有庫的鏈接限制之後的又一次重大調整。

從今以後,不論是native層的NDK還是 java層的SDK,我們只能使用Google提供的、公開的標准介面。這對開發者以及用戶乃至整個Android生態,當然是一件好事。

但這也同時意味著Android上的各種黑科技有可能會逐漸走向消亡。

公共 SDK 介面是在 Android 框架軟體包索引 中記錄的那些介面

從 Android Pie 開始,對某些隱藏類、方法和欄位的訪問受到限制在 Pie 之前,通過簡單地使用反射來使用這些隱藏的非 SDK 組件非常容易。

但是,現在當嘗試訪問時,面向 API 28 (Pie) 或更高版本的應用程序將遇到 ClassNotFoundException、NoSuchMethodError 或 NoSuchFieldException Activity#createDialog() 。

先來看看系統是如何實現這個限制的。

通過反射或者JNI訪問非公開介面時會觸發警告/異常等,那麼不妨跟蹤一下反射的流程,看看系統到底在哪一步做的限制。

先來看一下 java.lang.Class.getDeclaredMethod(String) :

其中看一下 ShouldBlockAccessToMember 的調用,如果它返回false,那麼直接返回 nullptr ,上層就會拋 NoSuchMethodXXX 異常;也就觸發系統的限制了。

源碼如下:

繼續跟蹤下 GetMemberAction方法 :

繼續跟蹤GetMemberActionImpl方法:

其中調用到了

只要 IsExempted 方法返回 true,就算這個方法在黑名單中,依然會被放行然後允許被調用。

IsExempted 方法:

繼續跟蹤傳遞進來的參數 runtime->GetHiddenApiExemptions() 發現也是 runtime 裡面的一個參數.

這樣就可以直接修改 hidden_api_exemptions_ 繞過去限制。

Java 層的,有一個對應的 VMRuntime.setHiddenApiExemptions 方法,通過 VMRuntime.setHiddenApiExemptions 設置下豁免條件,就能愉快滴使用反射了。

IsExempted 方法裡面調用 DoesPrefixMatch 方法。DoesPrefixMatch是對方法簽名進行前綴匹配。所有Java方法類的簽名都是以 L 開頭,這樣就可以直接傳個 L 進去,所有的隱藏API全部被赦免了!

另一種繞過 Android P以上非公開API限制的辦法

③ android hid是什麼意思

機器人藏起來了,Android 除了安卓系統的意思,還有機器人的意思

④ android怎樣調用@hide和internal API

Android有兩種類型的API是不能經由SDK訪問的。

第一種是位於com.android.internal包中的API。我將稱之為internal API。第二種API類型是一系列被標記為@hide屬性的類和方法。從嚴格意義上來講,這不是一個單一的API,而是一組小的被隱藏的API,但我仍將其假設為一種API,並稱之為hidden API。

Hidden API 例子

你可以查看一下android的源碼,並能找到一些變數、函數和類等,都被@hide屬性標記了。

下面的例子就是在WifiManager(API 10源碼)中隱藏的變數。

另一個例子是在WifiManager(API 10源碼)中隱藏了setWifiApEnabled函數。

因此,只要你看到@hide屬性,那你看到的就是hidden API。

Internal和hidden API的區別

Hidden API之所以被隱藏,是想阻止開發者使用SDK中那些未完成或不穩定的部分(介面或架構)。舉個例子,Bluetooth API在API 5(Android 2.0)上才開放;在API 3 和4上都是用@hide屬性隱藏了。當這些API被驗證和清理後,Google的開發者會移除@hide屬性,並讓其在API 5官方化。很多地方在API 4 和5之間發生了變化。如果你的程序依賴某些隱藏的API,當其部署到新的平台上時,就有可能陷入困境。

對於internal API來說,從來都沒有計劃將其開放出來。它就是Android的「內部廚房」,對開發者來說,應該將其視作黑盒。凡事都會有變化的。如果你依賴某些internal API,也有可能在新的Android release上,這些internal API發生變化,從而令你失望。

總結一下區別:

Hidden API = 進行中的工作;

Internal API = 黑盒;

Internal和hidden API的編譯時 vs. 運行時

當你使用Android SDK進行開發的時候,你引用了一個非常重要的jar文件——android.jar。它位於Android SDK平台的文件夾中(SDK_DIR/platforms/platform-X/android.jar,其中,X表示API等級)。這個android.jar移掉了com.android.internal包中所有的類,也移掉了所有標記有@hide的類,枚舉,欄位和方法。

但當你在設備上啟動應用程序時,它將載入framework.jar(簡單來說,它和android.jar等同),而其未移掉internal API和hidden API。(但它對開發者來說,並不能友好地訪問,因此,我將向大家展示不通過反射如何使用這些API)。

關於internal API,還有一件事需要說明。Eclipse的ADT插件增加了一個額外的規則,那就是禁止使用com.android.internal包中的任何東西。所以,即便是我們可以拿到最原始的android.jar(未刪減版),也沒有輕松的辦法通過Eclipse使用這些internal API。

你可以親自檢查一下。創建一個新的Android工程(或者使用已有的)。查看一下它引用的類庫(右擊project Properties –> Java Build Path –> Libraries)。

重要的總結:internal和hidden API在SDK中是按照一樣的方式處理的(都從android.jar中移除了),但internal API更慘的是,還被Eclipse的ADT插件顯式禁止了。

不通過反射使用internal和hidden API

這些文章的終極目標是讓開發者能夠不通過反射使用Internal和Hidden API。如果你完成了接下來部分中描述的步驟,你將能使用這些Internal和Hidden API,如同公開的API。你不再需要使用反射。

註:如果你正在使用這些非公開的API,你必須知道,你的程序有著極大的風險。基本上,無法保證在下一次的Android OS更新時,這些API不被破壞,也無法保證不同的運營商有著一致的行為。你自己決定吧。

接下來有三個場景:

1. Internal 和hidden API都可用(場景A)

2. 只Hidden API可用(場景B)

3. 只Internal API可用(場景C)

場景A是B、C的總和。場景B是最簡單的一個(不需要對Eclipse的ADT修改)。

場景A:閱讀Part1, 2, 3, 4, 5

場景B:閱讀Part1, 2, 3, 5

場景C:閱讀Part1, 2, 3, 4, 5

我解釋了為什麼我們不通過反射就會很難使用internal和hidden API。這是因為android.jar中就沒包含這些API,因此,沒人能夠在編譯時引用這些類。

這篇文章將描述如何還原最初的android.jar。這將允許我們像使用公開的API那樣使用internal和hidden API。

如何得到原版android.jar?

我們需要修改android.jar,這樣它才能包含所有的*.class文件(包括internal和hidden API類)。有兩種辦法:

1) Android是一個開源工程。我們可以下載源碼並搭建編譯環境,這樣它就不能移除那些internal和hidden的類了。這個辦法比較困難;

2) 每個模擬器或真機在運行時都會有一個等同android.jar的東西。我們可以從這里拿到jar文件,提取出原始的.class文件,並拷貝到Android SDK的android.jar中。

我將採用方案2。它易於開始,還不需要搭建Linux環境及編譯環境等。

從設備上獲取framework.jar

你可以使用命令行(adb pull)從模擬器或設備上下載文件,或者使用DDMS(藉助Eclipse或SDK中的應用)。

注意:模擬器通常在.dex文件中包含代碼,而真機一般在優化版的dex文件中包含代碼——odex文件。操作odex文件比較困難,這也是為什麼我選擇模擬器的原因。

與Android SDK中的android.jar等同的文件是framework.jar。這個文件位於設備的:/system/framework/framework.jar

adb pull /system/framework/framework.jar

當framework.jar從設備上下下來之後,重命名為framework.zip並解壓到獨立的文件夾中,看起來是這個樣子的:

classes.dex正是我們需要的。

創建framework-classes.zip

首先,我們需要把.dex文件轉換成.jar格式。你可以使用通用的工具dex2jar。只需要運行:

dev2jar classes.dex

當轉換結束時,你應該得到了classes.dex.dex2jar.jar文件。重命名為framework-classes.zip。使用zip查看器,進入到framework-classes.zip/com/android/internal/:

恭喜你,你已經擁有了所有的.class文件,包括internal和hidden API(盡管截圖只確認了internal部分)。

創建original-android.jar

Android SDK的android.jar位於ANDROID_SDK/platforms/android-X/android.jar(X表示API等級)。

拷貝android.jar成custom-android.jar。解壓至custom-android文件夾。將framework-classes.zip中所有的.class文件拷貝到custom-android文件夾中(你需要覆蓋所有已經存在的.class文件)。

然後,壓縮custom-android文件成original-android.zip。重命名為original-android.jar。

步驟總結

1. 選擇你的目標平台X

2. 創建目標平台X的模擬器

3. 啟動模擬器,下載/system/framework/framework.jar

4. 重命名framework.jar -> framework.zip

5. 從framework.zip中抽取classes.dex

6. 使用dex2jar工具,將其轉換成classes.jar

7. 重命名classes.jar -> framework-classes.zip

8. 拷貝android.jar –> custom-android.zip

9. 解壓custom-android.zip至custom-android文件夾

10. 將framework-classes.zip中所有文件拷貝至custom-android文件夾(覆蓋存在的文件)

11. 壓縮custom-android文件夾成original-android.zip

12. 重命名original-android.zip -> original-android.jar

打完收功。

⑤ 如何調用Android隱藏API

一、如何隱藏API的? 1) 在正常情況下,即不加@hide的時候,所有的public的類或者方法,在編譯時都會編譯生成到stub library的jar文件中。這個stub library其實是個空實現,但是它包含了所有的public方法。所以用這個stub library,應用開發者就可以在eclipse中進行開發了。 2) 但一旦加了@hide,那麼在編譯生成stublibrary時,凡是被@hide標記的類或者方法都被移除了。所以應用開發者就無法通過這個stub library「直接」調用被隱藏的類或者方法。如果強行在eclipse里調用隱藏的類或者方法,則eclipse會報錯。典型的例子就是Android SDK中的android.jar,這個stub library所包含的就是已經被移除的的API。上圖中,ActivityManager的forceStopPackage()方法在Android SDK中是無法找到的。 二、隱藏的API可以調用嗎? 1) 那麼應用開發者可以使用這些隱藏的API嗎? 答案是肯定的。在真實的運行環境中,所有的API都是存在的並且是被實現的。那麼很容易就會想到用「反射」。如果我們已經知道目標類的類名和方法名,以及參數列表,那麼這樣的方法即使被@hide了,我們依然可以通過反射來調用它。對於Java反射,這里我們不準備,不是很了解的同學請自行學習研究。下面是一個反射的例子。 IActivitManageram = ActivityManagerNative.getDefault(); Method forceStopPackage = am.getClass().getDeclaredMethod("forceStopPackage", String.class); forceStopPackage.setAccessible(true); forceStopPackage.invoke(am, yourpkgname); 2) 反射雖好,不過寫起來真麻煩,本來一個調用代碼,一行就可以搞定,但是現在用發射寫的話,需要好多行。有沒有其他更加方便的辦法呢,其實是有的。上面我們提到在Android SDK中的android.jar是一個閹割版,如果我們能生成一個完整版,這個問題就迎刃而解了。方法是現在整套Android源代碼,然後做一次完整的編譯。在out/target/common/obj/JAVA_LIBRARIES/目錄下可以根據需要提取自己所要的stublibrary。以framework為例:將out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar復制到eclipse開發環境中,用userlibrary的方式掛載,使其的優先順序比android.jar要高即可。 以下是在eclipse中的設置步驟: <ignore_js_op> <ignore_js_op> <ignore_js_op> <ignore_js_op> <ignore_js_op> <ignore_js_op> <ignore_js_op> <ignore_js_op> <ignore_js_op> 三、需要注意的一些問題 1) 無論是反射還是使用自編譯的stublibrary,只能解決調用隱藏API的問題,而無法越過許可權檢查。 2) Google之所以將有些API隱藏,有些原因可能是因為這些API屬於內部邏輯,不想對外暴露,也有可能是API介面還未最終確定下來。所以在低版本Android上的隱藏API不一定能在高版本的Android上使用。這點是一定要注意的。也就說隱藏API的兼容性比較差。因此利用反射調用隱藏API時,一定要注意根據Android的版本採用不同的方式去反射。

⑥ Android可以實現跟HID設備的通訊嗎Java/Linux

可以的Android SDK提供類跟方法可以實現跟HID設備通信,例如
UsbDeviceConnection 類的controlTransfer介面就可以實現。

⑦ Android可以實現跟HID設備的通訊嗎

HID設備是USB介面的,Android支持USB的讀取和操作。所以可以。

⑧ Android 藍牙HID模式怎麼向HID藍牙設備發送數據

要想實現這個目標,首先要想一想android設備和pc設備之間的通訊基礎是什麼?這個通訊技術必須是android和pc同時支持的,目前看來也就是wifi,藍牙。首先說一下藍牙,藍牙是一個提供個人區域網的安全無線電通訊技術,相對於wifi而言,藍牙的功耗相對較低,尤其是BLE技術使得藍牙的功耗可以和zigbee媲美了,並且android也支持了基於藍牙的socket操作。但是pc上的java部分對於藍牙的socket支持就不是很好了,實現起來比較麻煩。但是wifi雖然功耗相對藍牙而言比較高了點,但是實現起來非常容易,就是socket就好了!所以在第一版本中,可以先使用wifi作為傳輸技術。

⑨ android bluetooth hid協議的開發求助

Android Bluetooth HID實現詳解


Android 關於藍牙的部分使用的是BlueZ協議棧。但是直到目前2.3.3都沒有擴展HID的profile,只是實現了最基本的Handset和d2dp的profile,所以我們的工作涉及到從應用到jni三層的修改,具體修改文件如圖所示,綠色表示新建的類,橙色表示修改的類。

一. 本地層


路徑:framework/base/core/jni/

參照android_server_BluetoothA2dpService.cpp新建android_server_bluetoothHidServer.cpp。該類中主要是通過dbus對bluez協議棧的訪問,dbus 的通用方法都在android_bluetooth_common.cpp中實現,我們做的僅僅是通過dbus_func_args_async調用到bluez提供的input介面。

主要實現以下兩個方法函數:

static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) {


#ifdef HAVE_BLUETOOTH


LOGV(__FUNCTION__);


if (nat) {


const char *c_path = env->GetStringUTFChars(path, NULL);



bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,


c_path, "org.bluez.Input", "Connect",


DBUS_TYPE_INVALID);



env->ReleaseStringUTFChars(path, c_path);


return ret ? JNI_TRUE : JNI_FALSE;


}


#endif


return JNI_FALSE;


}



static jboolean disconnectSinkNative(JNIEnv *env, jobject object,


jstring path) {


#ifdef HAVE_BLUETOOTH


LOGV(__FUNCTION__);


if (nat) {


const char *c_path = env->GetStringUTFChars(path, NULL);



bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,


c_path, "org.bluez.Input", "Disconnect",


DBUS_TYPE_INVALID);



env->ReleaseStringUTFChars(path, c_path);


return ret ? JNI_TRUE : JNI_FALSE;


}


#endif


return JNI_FALSE;


}

這里要注意將該文件添加到AndroidRuntime.cpp和Android.mk中,否則不會編譯到動態庫中。

此部分編譯後最終生成libandroid_runtime.so並替換到system/libs下

二.Framework的java部分

路徑framework/base/java/android/server/中添加BluetoothHidService.java文件

路徑framework/base/java/android/bluetooth/中添加BluetoothHid.java和IBluetoothHid.aidl文件。


interface IBluetoothHid {


boolean connect(in BluetoothDevice device);


boolean disconnect(in BluetoothDevice device);


int getState(in BluetoothDevice device);


boolean setPriority(in BluetoothDevice device, int priority);


int getPriority(in BluetoothDevice device);


}

BluetoothHid.java中主要的兩個方法connect和disconnect間接地通過aidl訪問BluetoothHidService。這里主要是實現跨進程並為上層提供可直接訪問的方法。

由此framework的主要部分打包生成framework.Jar並最終部署到system/framework里。

三.應用(Settings.apk)

最後需要修改應用部分,應用部分的修改點比較分散,不想框架層那樣整塊模仿A2DP的樣子那麼方便,但也不是說jni部分有多麼容易。反而對於我這種對C語言不熟悉的人來說,修改jni是最頭疼得事了。好在藍牙HID這部分框架層的修改都是整塊進行的,理解上還算比價容易。

總的來說在Settings.apk中要修改的文件主要是這么幾個:

LocalBluetoothProfileManager.java這里主要提供一個HID的profile以便應用層訪問。建一個HIDProfile的class調用framework中的BluetoothHID。實際上就是通過bender機制調用了BluetoothHidService。

CashedBluetoothDevice中添加顯示藍牙鍵盤的圖標,BluetoothPairingDialog中則需要添加一段藍牙配對驗證處理的代碼,我是參照i9000中先彈出一個隨機數,然後在鍵盤中敲入相同的隨機數即配對成功,具體實現如下:


// HID


if (isDeviceKeyboard(mDevice)) {


String pin = String.format("%06d", Long.valueOf(Math


.abs(new Random().nextLong() % 1000000L)));


mPairingView.setVisibility(View.GONE);


messageView.setText(getString(


R.string.bluetooth_enter_keyboard_pin_msg, pin, name));



byte[] bytePin = BluetoothDevice.convertPinToBytes(pin);


if (bytePin != null) {


mDevice.setPin(bytePin);


}


}


……


}

轉載

閱讀全文

與hidapiandroid相關的資料

熱點內容
雙極壓縮機為什麼要先高壓 瀏覽:523
蘋果手機伺服器填什麼 瀏覽:828
android移動動畫效果 瀏覽:680
電子和伺服器是什麼意思 瀏覽:681
phpurl中文亂碼問題 瀏覽:891
程序員那麼可愛大結局陸漓產子 瀏覽:536
java如何從雲伺服器讀取本地文件 瀏覽:921
壓縮空氣軟管製作方法 瀏覽:911
天河三號演算法 瀏覽:924
php隊列教程 瀏覽:632
洪水命令 瀏覽:529
安卓怎麼弄成蘋果在線 瀏覽:435
谷歌web伺服器地址 瀏覽:898
安卓鎖屏圖片如何刪除 瀏覽:719
python3多進程編程 瀏覽:714
證明代碼是程序員寫的 瀏覽:397
演算法錯誤發現辦法 瀏覽:410
河南省醫院掛號是哪個app 瀏覽:629
冬日戀歌哪個APP能看 瀏覽:673
委內瑞拉加密貨 瀏覽:10