Làm thế nào để có được tên gói từ bất cứ nơi nào?


346

Tôi biết về tính khả dụng của Context.getApplicationContext ()View.getContext () , qua đó tôi thực sự có thể gọi Context.getPackageName () để lấy tên gói của ứng dụng.

Chúng hoạt động nếu tôi gọi từ một phương thức có sẵn Viewmột Activityđối tượng, nhưng nếu tôi muốn tìm tên gói từ một lớp hoàn toàn độc lập mà không có Viewhoặc Activity, có cách nào để làm điều đó (trực tiếp hay gián tiếp) không?


7
Câu trả lời được chấp nhận sẽ khiến ứng dụng của bạn thỉnh thoảng CRASH - đọc bình luận của AddDev & Turbo và cảm ơn cả hai vì đã đề xuất giải pháp.
nikib3ro

1
Bạn có thể không có lựa chọn nào khác, nhưng như một vấn đề thực tiễn tốt nhất tôi nói rằng tốt hơn là chuyển nó vào lớp bạn cần từ điểm Bối cảnh cuối cùng của bạn theo một cách nào đó. Bạn đang truy cập thông tin ngữ cảnh thời gian chạy từ một lớp không biết về Ngữ cảnh theo cách tĩnh - có mùi đối với tôi. Một cách tiếp cận khác là mã hóa nó ở đâu đó.
Adam

Câu trả lời:


487

Một ý tưởng là có một biến tĩnh trong hoạt động chính của bạn, ngay lập tức là tên gói. Sau đó chỉ cần tham khảo biến đó.

Bạn sẽ phải khởi tạo nó trong onCreate()phương thức của hoạt động chính :

Toàn cầu đến lớp:

public static String PACKAGE_NAME;

Sau đó..

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    PACKAGE_NAME = getApplicationContext().getPackageName();
}

Sau đó bạn có thể truy cập nó thông qua Main.PACKAGE_NAME.


3
Đây có vẻ là giải pháp thiết thực nhất đối với tôi ngay bây giờ nhưng nó yêu cầu tôi tạo một lớp con của hoạt động ... +1 ngay bây giờ.
ef2011

1
Chỉ cần tìm thấy một tài liệu tham khảo tương tự: stackoverflow.com/questions/2002288/ trên
ef2011

13
Sự hiểu biết của tôi là finallàm cho nó bất biến, chỉ có thể khởi tạo trong một hàm tạochỉ một lần . onCreate()không phải là một nhà xây dựng. Hãy sửa nếu tôi nhầm.
ef2011

79
Cách tiếp cận này không chính xác. Ví dụ: nếu ứng dụng của bạn đi vào nền khi bạn đang ở chế độ tạm thời, và sau đó được khôi phục. Không thể gọi onCreate () của hoạt động chính của bạn và PACKAGE_NAME của bạn sẽ không có giá trị!. Ngoài ra, nếu ứng dụng của bạn có 10 điểm vào và không có "hoạt động chính" rõ ràng thì sao? Bạn có thể kiểm tra câu trả lời của tôi tại câu hỏi này để biết cách tiếp cận chính xác
Addev

3
@Turbo, nếu Android giết quá trình, onCreatedù sao cũng sẽ phải gọi lại, vì vậy giải pháp này vẫn không phải là vấn đề.
John Leehey

276

Nếu bạn sử dụng plugin gradle-android để xây dựng ứng dụng của mình, thì bạn có thể sử dụng

BuildConfig.APPLICATION_ID

để lấy tên gói từ bất kỳ phạm vi nào, bao gồm một tĩnh.


23
Đó là cách thích hợp, nên là câu trả lời được chấp nhận.
aberaud

4
Lưu ý: Với các bản dựng đa hương vị, điều này sẽ trả về (tùy thuộc vào quá trình nhập được sử dụng để có quyền truy cập vào lớp BuildConfig), tên gói của cấu hình mặc định không phải là tên gói của hương vị.
Rolf

2
@Rolf Điều đó không đúng, nó sẽ trả lại đúng tên gói ứng dụng;) có thể bạn đang nhầm nó với tên gói của các lớp java của bạn
Billda

28
Hãy cẩn thận nếu sử dụng điều này trong một dự án thư viện - điều này sẽ không hoạt động.
zyamys

6
Hãy cẩn thận nếu sử dụng điều này trong nhiều mô-đun bên trong một dự án.
dùng802421

68

Nếu với từ "bất cứ nơi nào" bạn có nghĩa là không có một từ rõ ràng Context(ví dụ từ một luồng nền), bạn nên định nghĩa một lớp trong dự án của bạn như:

public class MyApp extends Application {
    private static MyApp instance;

    public static MyApp getInstance() {
        return instance;
    }

    public static Context getContext(){
        return instance;
        // or return instance.getApplicationContext();
    }

    @Override
    public void onCreate() {
        instance = this;
        super.onCreate();
    }
}

Sau đó, trong manifestbạn cần thêm lớp này vào Nametrường ở Applicationtab. Hoặc chỉnh sửa xml và đặt

<application
    android:name="com.example.app.MyApp"
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    .......
    <activity
        ......

và sau đó từ bất cứ nơi nào bạn có thể gọi

String packagename= MyApp.getContext().getPackageName();

Hy vọng nó giúp.


Đây không phải là luồng an toàn, nhưng có lẽ bạn có thể thoát khỏi nó nếu luồng nền được bắt đầu bởi hoạt động này sau này.
tomwhipple

3
Đây là luồng an toàn vì tham chiếu đến ví dụ là điều đầu tiên được đặt khi ứng dụng được khởi chạy
Addev

17
Mỗi vấn đề này: code.google.com/p/android/issues/detail?id=8727 Các đối tượng ContentProvider được tạo trước đối tượng Ứng dụng, dường như trái với tài liệu, nhưng rõ ràng cũng theo và theo thiết kế. Điều này có thể dẫn đến trường hợp của bạn vẫn không được đặt nếu getInstance () được gọi trong quá trình khởi tạo của ContentProvider.
Carl

3
Tài liệu trên Application.onCreate()đã được thay đổi để phản ánh điều này: hiện tại nó ghi rõ "Được gọi khi ứng dụng bắt đầu, trước mọi đối tượng hoạt động, dịch vụ hoặc người nhận (không bao gồm nhà cung cấp nội dung)".
Paul Lammertsma

2
Đây phải là câu trả lời được chọn, bởi vì bối cảnh sẽ không bao giờ chết cho dù hoạt động nào đang chạy.
Elad Nava

43

Nếu bạn sử dụng gradle build, hãy sử dụng cái này: BuildConfig.APPLICATION_IDđể lấy tên gói của ứng dụng.


6
ID ứng dụng và tên gói là những thứ khác nhau. ID ứng dụng được xác định thông qua tệp gradle.build và tên gói được xác định trong Bản kê khai. Mặc dù chúng thường có cùng giá trị, nhưng chúng cũng thường khác nhau, trong các kịch bản xây dựng phức tạp hơn. Người ta có thể gán các ID ứng dụng khác nhau cho các cấu hình xây dựng khác nhau trong khi tên gói không thay đổi.
Uli

3
@Uli Dành cho những người muốn biết các sắc thái trong một số công cụ chi tiết hơn một chút.android.com / tech
Kevin Lee

10
@Uli Điều đó đang được nói, ngay cả khi applicationId trong app.gradle trì hoãn từ góiName bên trong AndroidManifest.xml, gọi bối cảnh.getPackageName () trả về applicationId chứ không phải packName bên trong AndroidManifest.xml. Điểm quan trọng của hệ thống xây dựng mới là tách rời cả hai, vì vậy applicationId là tên gói thực tế của ứng dụng được biết đến với Google Play và với thiết bị được cài đặt trên - nó không thể thay đổi sau khi triển khai. Quan điểm của tôi là, sử dụng BuildConfig.APPLICATION_ID là ổn. Hãy cho tôi biết nếu tôi nhầm (:
Kevin Lee

2
@kevinze Hoàn toàn chính xác! Tôi đã chạy thử để kiểm tra lại. Cảm ơn đã làm rõ / sửa chữa.
Uli

5
private String getApplicationName(Context context, String data, int flag) {

   final PackageManager pckManager = context.getPackageManager();
   ApplicationInfo applicationInformation;
   try {
       applicationInformation = pckManager.getApplicationInfo(data, flag);
   } catch (PackageManager.NameNotFoundException e) {
       applicationInformation = null;
   }
   final String applicationName = (String) (applicationInformation != null ? pckManager.getApplicationLabel(applicationInformation) : "(unknown)");
   return applicationName;

}

4

Bạn có thể nhận được tên gói của bạn như vậy:

$ /path/to/adb shell 'pm list packages -f myapp'
package:/data/app/mycompany.myapp-2.apk=mycompany.myapp

Dưới đây là các tùy chọn:

$ adb
Android Debug Bridge version 1.0.32
Revision 09a0d98bebce-android

 -a                            - directs adb to listen on all interfaces for a connection
 -d                            - directs command to the only connected USB device
                                 returns an error if more than one USB device is present.
 -e                            - directs command to the only running emulator.
                                 returns an error if more than one emulator is running.
 -s <specific device>          - directs command to the device or emulator with the given
                                 serial number or qualifier. Overrides ANDROID_SERIAL
                                 environment variable.
 -p <product name or path>     - simple product name like 'sooner', or
                                 a relative/absolute path to a product
                                 out directory like 'out/target/product/sooner'.
                                 If -p is not specified, the ANDROID_PRODUCT_OUT
                                 environment variable is used, which must
                                 be an absolute path.
 -H                            - Name of adb server host (default: localhost)
 -P                            - Port of adb server (default: 5037)
 devices [-l]                  - list all connected devices
                                 ('-l' will also list device qualifiers)
 connect <host>[:<port>]       - connect to a device via TCP/IP
                                 Port 5555 is used by default if no port number is specified.
 disconnect [<host>[:<port>]]  - disconnect from a TCP/IP device.
                                 Port 5555 is used by default if no port number is specified.
                                 Using this command with no additional arguments
                                 will disconnect from all connected TCP/IP devices.

device commands:
  adb push [-p] <local> <remote>
                               - copy file/dir to device
                                 ('-p' to display the transfer progress)
  adb pull [-p] [-a] <remote> [<local>]
                               - copy file/dir from device
                                 ('-p' to display the transfer progress)
                                 ('-a' means copy timestamp and mode)
  adb sync [ <directory> ]     - copy host->device only if changed
                                 (-l means list but don't copy)
  adb shell                    - run remote shell interactively
  adb shell <command>          - run remote shell command
  adb emu <command>            - run emulator console command
  adb logcat [ <filter-spec> ] - View device log
  adb forward --list           - list all forward socket connections.
                                 the format is a list of lines with the following format:
                                    <serial> " " <local> " " <remote> "\n"
  adb forward <local> <remote> - forward socket connections
                                 forward specs are one of:
                                   tcp:<port>
                                   localabstract:<unix domain socket name>
                                   localreserved:<unix domain socket name>
                                   localfilesystem:<unix domain socket name>
                                   dev:<character device name>
                                   jdwp:<process pid> (remote only)
  adb forward --no-rebind <local> <remote>
                               - same as 'adb forward <local> <remote>' but fails
                                 if <local> is already forwarded
  adb forward --remove <local> - remove a specific forward socket connection
  adb forward --remove-all     - remove all forward socket connections
  adb reverse --list           - list all reverse socket connections from device
  adb reverse <remote> <local> - reverse socket connections
                                 reverse specs are one of:
                                   tcp:<port>
                                   localabstract:<unix domain socket name>
                                   localreserved:<unix domain socket name>
                                   localfilesystem:<unix domain socket name>
  adb reverse --norebind <remote> <local>
                               - same as 'adb reverse <remote> <local>' but fails
                                 if <remote> is already reversed.
  adb reverse --remove <remote>
                               - remove a specific reversed socket connection
  adb reverse --remove-all     - remove all reversed socket connections from device
  adb jdwp                     - list PIDs of processes hosting a JDWP transport
  adb install [-lrtsdg] <file>
                               - push this package file to the device and install it
                                 (-l: forward lock application)
                                 (-r: replace existing application)
                                 (-t: allow test packages)
                                 (-s: install application on sdcard)
                                 (-d: allow version code downgrade)
                                 (-g: grant all runtime permissions)
  adb install-multiple [-lrtsdpg] <file...>
                               - push this package file to the device and install it
                                 (-l: forward lock application)
                                 (-r: replace existing application)
                                 (-t: allow test packages)
                                 (-s: install application on sdcard)
                                 (-d: allow version code downgrade)
                                 (-p: partial application install)
                                 (-g: grant all runtime permissions)
  adb uninstall [-k] <package> - remove this app package from the device
                                 ('-k' means keep the data and cache directories)
  adb bugreport                - return all information from the device
                                 that should be included in a bug report.

  adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]
                               - write an archive of the device's data to <file>.
                                 If no -f option is supplied then the data is written
                                 to "backup.ab" in the current directory.
                                 (-apk|-noapk enable/disable backup of the .apks themselves
                                    in the archive; the default is noapk.)
                                 (-obb|-noobb enable/disable backup of any installed apk expansion
                                    (aka .obb) files associated with each application; the default
                                    is noobb.)
                                 (-shared|-noshared enable/disable backup of the device's
                                    shared storage / SD card contents; the default is noshared.)
                                 (-all means to back up all installed applications)
                                 (-system|-nosystem toggles whether -all automatically includes
                                    system applications; the default is to include system apps)
                                 (<packages...> is the list of applications to be backed up.  If
                                    the -all or -shared flags are passed, then the package
                                    list is optional.  Applications explicitly given on the
                                    command line will be included even if -nosystem would
                                    ordinarily cause them to be omitted.)

  adb restore <file>           - restore device contents from the <file> backup archive

  adb disable-verity           - disable dm-verity checking on USERDEBUG builds
  adb enable-verity            - re-enable dm-verity checking on USERDEBUG builds
  adb keygen <file>            - generate adb public/private key. The private key is stored in <file>,
                                 and the public key is stored in <file>.pub. Any existing files
                                 are overwritten.
  adb help                     - show this help message
  adb version                  - show version num

scripting:
  adb wait-for-device          - block until device is online
  adb start-server             - ensure that there is a server running
  adb kill-server              - kill the server if it is running
  adb get-state                - prints: offline | bootloader | device
  adb get-serialno             - prints: <serial-number>
  adb get-devpath              - prints: <device-path>
  adb remount                  - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write
  adb reboot [bootloader|recovery]
                               - reboots the device, optionally into the bootloader or recovery program.
  adb reboot sideload          - reboots the device into the sideload mode in recovery program (adb root required).
  adb reboot sideload-auto-reboot
                               - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.
  adb sideload <file>          - sideloads the given package
  adb root                     - restarts the adbd daemon with root permissions
  adb unroot                   - restarts the adbd daemon without root permissions
  adb usb                      - restarts the adbd daemon listening on USB
  adb tcpip <port>             - restarts the adbd daemon listening on TCP on the specified port

networking:
  adb ppp <tty> [parameters]   - Run PPP over USB.
 Note: you should not automatically start a PPP connection.
 <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1
 [parameters] - Eg. defaultroute debug dump local notty usepeerdns

adb sync notes: adb sync [ <directory> ]
  <localdir> can be interpreted in several ways:

  - If <directory> is not specified, /system, /vendor (if present), /oem (if present) and /data partitions will be updated.

  - If it is "system", "vendor", "oem" or "data", only the corresponding partition
    is updated.

environment variables:
  ADB_TRACE                    - Print debug information. A comma separated list of the following values
                                 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp
  ANDROID_SERIAL               - The serial number to connect to. -s takes priority over this if given.
  ANDROID_LOG_TAGS             - When used with the logcat option, only these debug tags are printed.

3

Bạn có thể sử dụng phương pháp không có giấy tờandroid.app.ActivityThread.currentPackageName() :

Class<?> clazz = Class.forName("android.app.ActivityThread");
Method method  = clazz.getDeclaredMethod("currentPackageName", null);
String appPackageName = (String) method.invoke(clazz, null);

Hãy cẩn thận : Điều này phải được thực hiện trên luồng chính của ứng dụng.

Cảm ơn bài viết trên blog này cho ý tưởng: http://blog.javia.org/static-the-android-application-package/ .


2

Đối với những người đang sử dụng Gradle, như @Billda đã đề cập, bạn có thể lấy tên gói thông qua:

BuildConfig.APPLICATION_ID

Điều này cung cấp cho bạn tên gói được khai báo trong lớp ứng dụng của bạn:

android {
    defaultConfig {
        applicationId "com.domain.www"
    }
}

Nếu bạn muốn lấy tên gói được sử dụng bởi các lớp java của bạn (đôi khi khác với applicationId), bạn có thể sử dụng

BuildConfig.class.getPackage().toString()

Nếu bạn bối rối không biết sử dụng cái nào, hãy đọc ở đây :

Lưu ý: ID ứng dụng được sử dụng để gắn trực tiếp với tên gói của mã của bạn; vì vậy một số API Android sử dụng thuật ngữ "tên gói" trong tên phương thức và tên tham số của chúng, nhưng đây thực sự là ID ứng dụng của bạn. Ví dụ: phương thức Context.getPackageName () trả về ID ứng dụng của bạn. Không cần phải chia sẻ tên gói thực sự của mã bên ngoài mã ứng dụng của bạn.


bạn đã sử dụng mã nào vui lòng cung cấp chính xác lỗi bạn có.
user1506104

1
PackageInfo pinfo = this.getPackageManager().getPackageInfo(getPackageName(), 0);
         String sVersionCode = pinfo.versionCode; // 1
         String sVersionName = pinfo.versionName; // 1.0
         String sPackName = getPackageName(); // cz.okhelp.my_app
         int nSdkVersion = Integer.parseInt(Build.VERSION.SDK); 
         int nSdkVers = Build.VERSION.SDK_INT; 

Hy vọng nó sẽ làm việc.


0

Tạo một mô-đun java để được chạy ban đầu khi bắt đầu ứng dụng của bạn. Mô-đun này sẽ mở rộng lớp Ứng dụng Android và sẽ khởi tạo bất kỳ biến ứng dụng toàn cầu nào và cũng chứa các thói quen tiện ích trên toàn ứng dụng -

public class MyApplicationName extends Application {

    private final String PACKAGE_NAME = "com.mysite.myAppPackageName";

    public String getPackageName() { return PACKAGE_NAME; }
}

Tất nhiên, điều này có thể bao gồm logic để có được tên gói từ hệ thống Android; tuy nhiên, ở trên là mã nhỏ hơn, nhanh hơn và sạch hơn so với lấy từ Android.

Hãy chắc chắn đặt một mục trong tệp AndroidManifest.xml để yêu cầu Android chạy mô-đun ứng dụng của bạn trước khi chạy bất kỳ hoạt động nào -

<application 
    android:name=".MyApplicationName" 
    ...
>

Sau đó, để lấy tên gói từ bất kỳ mô-đun nào khác, hãy nhập

MyApp myApp = (MyApp) getApplicationContext();
String myPackage = myApp.getPackageName();

Sử dụng một mô-đun ứng dụng cũng cung cấp cho bạn một bối cảnh cho các mô-đun cần nhưng không có bối cảnh.


0

Sử dụng: BuildConfig.APPLICATION_ID để nhận TÊN GÓI ở mọi nơi (ví dụ: dịch vụ, người nhận, hoạt động, đoạn, v.v.)

Ví dụ: Chuỗi PackageName = BuildConfig.APPLICATION_ID;


0

Chỉ cần nhập Android.app thì bạn có thể sử dụng: <br/>Application.getProcessName()<br/>

Lấy Tên quy trình ứng dụng hiện tại mà không có ngữ cảnh, chế độ xem hoặc hoạt động.

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.