@Hide có nghĩa là gì trong mã nguồn Android?


120

Đối với Activitymã nguồn , dòng 3898 (gần dưới cùng):

/**
 * @hide
 */
public final boolean isResumed() {
    return mResumed;
}

Nghĩa @hidelà gì?

Tôi thấy tôi public class ChildActivity extends Activity { ... }không thể sử dụng / xem Activity.isResumed(). Điều này có bình thường không? Làm thế nào tôi có thể truy cập nó?

Câu trả lời:


182

Android có hai loại API không thể truy cập thông qua SDK.

Cái đầu tiên nằm trong gói com.android.internal. Loại API thứ hai là một tập hợp các lớp và phương thức được đánh dấu bằng thuộc tính @hide Javadoc .

Bắt đầu từ Android 9 (API cấp 28), Google đưa ra các hạn chế mới đối với việc sử dụng các giao diện không phải SDK , dù là trực tiếp, qua phản chiếu hay qua JNI. Những hạn chế này được áp dụng bất cứ khi nào một ứng dụng tham chiếu đến giao diện không phải SDK hoặc cố gắng lấy tay cầm của nó bằng cách sử dụng phản chiếu hoặc JNI.

Nhưng trước API cấp 28, các phương thức ẩn vẫn có thể được truy cập thông qua phản chiếu Java. Các @hidethuộc tính chỉ là một phần của Javadoc (droiddoc cũng), do đó @hidechỉ đơn giản có nghĩa là phương pháp / lớp / trường được loại trừ khỏi các tài liệu API.

Ví dụ, checkUidPermission()phương thức được ActivityManager.javasử dụng @hide:

/** @hide */
public static int checkUidPermission(String permission, int uid) {
    try {
        return AppGlobals.getPackageManager()
                .checkUidPermission(permission, uid);
    } catch (RemoteException e) {
        // Should never happen, but if it does... deny!
        Slog.e(TAG, "PackageManager is dead?!?", e);
    }
    return PackageManager.PERMISSION_DENIED;
}

Tuy nhiên, chúng ta có thể gọi nó bằng cách phản ánh:

Class c;
c = Class.forName("android.app.ActivityManager");
Method m = c.getMethod("checkUidPermission", new Class[] {String.class, int.class});
Object o = m.invoke(null, new Object[]{"android.permission.READ_CONTACTS", 10010});

1
xin chào @StarPinkER tôi có thể cấp quyền cho "android.permission.CHANGE_COMPONENT_ENABLED_STATE" bằng cách sử dụng api ẩn hoặc nội bộ hoặc bằng cách phản ứng lại không?
Hardik

1
Kiểm tra câu trả lời này đầu tiên. Quyền này là một chữ ký / quyền hệ thống. Trong hầu hết các trường hợp, bạn không thể nhận được quyền này trừ khi đó là các ứng dụng hệ thống. Điều đó có nghĩa là bạn cần sửa đổi Nguồn Android để chấp nhận ứng dụng của mình hoặc đặt ứng dụng của bạn thành một ứng dụng hệ thống và ký tên vào ứng dụng đó. Tuy nhiên, bạn sẽ không thể làm điều này trừ khi bạn đang tạo Hệ thống Android của riêng mình. Phản xạ có thể xử lý "ẩn" nhưng nó không thể thay đổi logic của Hệ thống bảo mật Android. Bạn có thể tưởng tượng cách chúng ta có thể dễ dàng tấn công Thiết bị Android nếu chúng ta có thể làm điều này. @Hardik
StarPinkER

2
Cảm ơn vì câu trả lời, nhưng tôi nghĩ có hai vấn đề trong câu trả lời, hãy sửa cho tôi nếu tôi sai. Tôi gặp lỗi classnotfound nếu cố gắng tìm nó bằng "ActivityManager" thay vì "android.app.ActivityManager" và "m.invoke (c," dường như phải là "m.invoke (null" đối với các phương thức tĩnh và "m. invoke (o, ", trong đó o là một đối tượng kiểu c, cho các phương pháp năng động Xin lỗi vì ngữ pháp Ba Lan của tôi :).
lindenrovio

3
Chỉ cần lưu ý về phản ánh: Vì các phương thức / trường đó không phải là một phần của SDK chính thức, nên không có gì đảm bảo rằng chúng sẽ có mặt trong bất kỳ bản sửa đổi Android nào trong tương lai.
sstn

2
Nếu chú thích chỉ xóa phương thức khỏi tài liệu, tại sao tôi vẫn không thể sử dụng nó trong mã?
Javier Delgado

25
  1. @hideđược sử dụng cho những thứ cần hiển thị vì nhiều lý do nhưng không phải là một phần của API đã xuất bản. Chúng sẽ không được đưa vào tài liệu khi nó tự động trích xuất API từ nguồn.

  2. Bạn nói đúng, bạn không thể ghi đè nó. Điều này là bình thường, đó là do thiết kế, vì nó được đánh dấu là final. Bạn sẽ có thể sử dụng nó, mặc dù một trình soạn thảo có thể không hiển thị nó cho bạn như một trong những lựa chọn trong bất kỳ nội dung nào mà nó sử dụng vì nó được đánh dấu bằng @hidevà bạn nên lưu ý điểm 3 bên dưới.

  3. Bạn hoàn toàn không nên sử dụng nó vì nó không phải là một phần của API và các nhà phát triển có thể xóa nó bất cứ khi nào họ muốn. Họ thậm chí sẽ được trong phạm vi quyền của họ, nếu họ có khuynh hướng tàn bạo, thay thế nó bằng một chức năng làm hỏng thiết bị mà nó chạy (mặc dù có thể không theo nghĩa pháp lý chặt chẽ).


Oh yea ... đó là finaltất nhiên tôi không thể ghi đè nó. Xin lỗi đó là sai lầm của tôi: x
Midnite

Ý bạn là, nó nằm publictrên tất cả các lớp trong giai đoạn phát triển. Nhưng nó hoạt động giống như privatehoặc /*package*/đối với những người dùng như chúng tôi?
midnite

Hmm ... Đó chỉ là một nhận xét. tôi hiểu ý nghĩa của nó. Nhưng điều gì và ở đâu để thực thi hành vi này ở cấp mã?
midnite

1
Tại sao nó công khai, tôi thực sự không thể bình luận. Có thể việc triển khai mã Activityđược trải rộng trên nhiều lớp và tất cả chúng đều cần truy cập thành viên này. Điểm mấu chốt là, nó công khai nhưng không phải là một phần của API, nghĩa là bạn tự chịu rủi ro khi sử dụng nó.
paxdiablo

1
@midnite, Eclipse có trình biên dịch Java của riêng nó, không nghi ngờ gì được tích hợp với nội dung intellisense. Tôi sẽ đề xuất nếu bạn biên dịch điều này bằng Java SDK, nó sẽ biên dịch tốt. Không phải là tôi muốn nói điều này tất nhiên, xem điểm 3.
paxdiablo

4

Các @hidechú thích có nghĩa là giao diện này không phải là một phần của API công cộng và không nên được sử dụng trong mã của bạn. Các phương pháp này chỉ dành cho mục đích sử dụng nội bộ của AOSP.

Google đã thực sự bắt đầu hạn chế việc sử dụng các giao diện không phải sdk . Điều này bao gồm các giao diện được đánh dấu bằng@hide

Các phương pháp được phân loại thành bốn danh sách:

  • danh sách trắng: SDK
  • light-greylist: các trường / phương thức không phải SDK vẫn có thể truy cập được.
  • dark-greylist:
    • Đối với các ứng dụng có SDK mục tiêu dưới API cấp 28: cho phép mỗi lần sử dụng giao diện danh sách màu xám tối.
    • Đối với các ứng dụng có SDK mục tiêu là API cấp 28 trở lên: hành vi tương tự như danh sách đen
  • danh sách đen: bị hạn chế bất kể SDK mục tiêu. Nền tảng sẽ hoạt động như thể không có giao diện. Ví dụ: nó sẽ ném NoSuchMethodError / NoSuchFieldException bất cứ khi nào ứng dụng cố gắng sử dụng nó và sẽ không bao gồm nó khi ứng dụng muốn biết danh sách các trường / phương thức của một lớp cụ thể.

Danh sách có thể được tìm thấy tại đây: https://android.googlesource.com/platform/prebuilts/runtime/+/master/appcompat

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.