【问题标题】:How to get package name from anywhere?如何从任何地方获取包名?
【发布时间】:2011-09-29 04:59:33
【问题描述】:

我知道Context.getApplicationContext()View.getContext() 的可用性,通过它们我实际上可以调用Context.getPackageName() 来检索应用程序的包名称。

如果我从可以使用ViewActivity 对象的方法调用它们,它们会起作用,但是如果我想从没有ViewActivity 的完全独立的类中找到包名,有没有办法(直接或间接)?

【问题讨论】:

  • 接受的答案会导致您的应用程序偶尔崩溃 - 阅读 AddDev 和 Turbo 提供的 cmets 并感谢他们提出解决方案。
  • 您可能没有其他选择,但作为最佳实践,我会说最好以某种方式从最后一个上下文点将它传递给您需要它的类。您正在从一个不以静态方式了解上下文的类访问运行时上下文信息 - 对我来说很难闻。另一种方法是在某处对其进行硬编码。

标签: android package android-context


【解决方案1】:

只需使用此代码

val packageName = context.packageName 

【讨论】:

    【解决方案2】:

    这在 kotlin 中适用于我

           override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
           
            var packageName=applicationContext.packageName // need to put this line
            Log.d("YourTag",packageName)
    }
    

    【讨论】:

      【解决方案3】:

      BuildConfig.APPLICATION_ID 和包可能并不总是相同。使用“buildConfigField”让 gradle 将包添加到 BuildConfig 并作为 BuildConfig.PACKAGE 访问。 https://developer.android.com/studio/build/gradle-tips

      defaultConfig {
          applicationId "com.example.app.name"
          minSdkVersion 24
          targetSdkVersion 29
          versionCode 1
          versionName '0.1.0'
          testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
          buildConfigField("String", "PACKAGE", "\"com.example.app\"")
      }
      

      【讨论】:

        【解决方案4】:

        只需导入Android.app,即可使用: <br/>Application.getProcessName()<br/>

        在没有上下文、视图或活动的情况下获取当前应用程序进程名称。

        【讨论】:

          【解决方案5】:

          使用: BuildConfig.APPLICATION_ID 在任何地方获取 PACKAGE NAME(即;服务、接收器、活动、片段等)

          示例: String PackageName = BuildConfig.APPLICATION_ID;

          【讨论】:

          • 如果您在库/模块中,这将获取库应用程序 ID。
          【解决方案6】:

          对于那些使用 Gradle 的人,正如@Billda 提到的,您可以通过以下方式获取包名称:

          BuildConfig.APPLICATION_ID
          

          这会为您提供在应用程序 gradle 中声明的包名称:

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

          如果您有兴趣获取您的 java 类使用的包名(有时与 applicationId 不同),您可以使用

          BuildConfig.class.getPackage().toString()
          

          如果您对使用哪一个感到困惑,read here:

          注意:应用程序 ID 过去直接与代码的 包裹名字;所以一些 Android API 在 他们的方法名和参数名,但这实际上是你的 应用程序 ID。例如,Context.getPackageName() 方法 返回您的应用程序 ID。无需共享您的代码 应用代码之外的真实包名。

          【讨论】:

          • 您使用了哪个代码?请提供您遇到的确切错误。
          【解决方案7】:
          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; 
          

          希望它会起作用。

          【讨论】:

            【解决方案8】:

            你可以使用undocumented方法android.app.ActivityThread.currentPackageName()

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

            警告:这必须在应用程序的主线程上完成。

            感谢这篇博文的创意:http://blog.javia.org/static-the-android-application-package/

            【讨论】:

              【解决方案9】:

              如果你使用 gradle-android-plugin 来构建你的应用,那么你可以使用

              BuildConfig.APPLICATION_ID
              

              从任何范围检索包名称,包括。一个静态的。

              【讨论】:

              • 这是正确的方法,应该是公认的答案。
              • 注意:对于多风格构建,这将返回(取决于用于访问 BuildConfig 类的导入)默认配置的包名,而不是风格的包名。
              • @Rolfツ 这不是真的,它会返回应用程序的正确包名;)也许你把它误认为是你的 java 类的包名
              • 如果在库项目中使用它要小心——这不起作用。
              • 如果在项目内的多个模块中使用它也要小心。
              【解决方案10】:

              你可以像这样得到你的包名:

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

              以下是选项:

              $ 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.
              

              【讨论】:

                【解决方案11】:

                创建一个 java 模块,以便在启动应用程序时初始运行。该模块将扩展 android Application 类,并将初始化任何全局应用程序变量,还包含应用程序范围的实用程序 -

                public class MyApplicationName extends Application {
                
                    private final String PACKAGE_NAME = "com.mysite.myAppPackageName";
                
                    public String getPackageName() { return PACKAGE_NAME; }
                }
                

                当然,这可以包括从android系统获取包名的逻辑;但是,上面的代码比从 android 获取的代码更小、更快、更简洁。

                确保在您的 AndroidManifest.xml 文件中放置一个条目,告诉 android 在运行任何活动之前运行您的应用程序模块 -

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

                然后,要从任何其他模块获取包名,请输入

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

                使用应用程序模块还可以为需要但没有上下文的模块提供上下文。

                【讨论】:

                  【解决方案12】:
                  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;
                  
                  }
                  

                  【讨论】:

                    【解决方案13】:

                    如果您使用 gradle build,请使用:BuildConfig.APPLICATION_ID 获取应用程序的包名。

                    【讨论】:

                    • 应用程序 ID 和包名是不同的东西。应用程序 ID 通过 gradle.build 文件定义,包名在 Manifest 中定义。虽然它们通常具有相同的值,但在更复杂的构建场景中它们也经常不同。在包名称保持不变的情况下,可以为不同的构建配置分配不同的应用程序 ID。
                    • @Uli 对于那些想更详细了解细微差别的人tools.android.com/tech-docs/new-build-system/…
                    • @Uli 话虽如此,即使 app.gradle 中的 applicationId 与 AndroidManifest.xml 中的 packageName 不同,调用 context.getPackageName() 也会返回 applicationId 而不是 AndroidManifest 中的 packageName。 xml。新构建系统的重点是将两者解耦,因此 applicationId 是应用程序的实际包名称,Google Play 和安装它的设备都知道 - 它在部署后无法更改。我的意思是,可以使用 BuildConfig.APPLICATION_ID。如果我弄错了,请告诉我(:
                    • @kevinze 完全准确!我进行了一次测试以仔细检查。感谢您的澄清/更正。
                    【解决方案14】:

                    如果使用“任何地方”这个词,您的意思是没有明确的Context(例如来自后台线程),您应该在您的项目中定义一个类,例如:

                    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();
                        }
                    }
                    

                    然后在您的manifest 中,您需要将此类添加到Application 选项卡的Name 字段中。或者编辑xml并放

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

                    然后从任何你可以打电话的地方

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

                    希望对你有帮助。

                    【讨论】:

                    • 这不是线程安全的,但如果后台线程稍后由此活动启动,您可能会摆脱它。
                    • 它是线程安全的,因为对实例的引用是应用程序启动时设置的第一件事
                    • 根据这个问题:code.google.com/p/android/issues/detail?id=8727 ContentProvider 对象是在 Application 对象之前创建的,这显然与文档相反,但显然也是按照设计的。如果在 ContentProvider 初始化期间调用 getInstance(),这可能会导致您的实例仍未设置。
                    • Application.onCreate() 上的文档已更改以反映这一点:它现在明确声明“在应用程序启动时调用,在任何活动、服务或接收器对象(不包括内容提供程序)之前调用”。
                    • 这应该是选择的答案,因为无论正在运行什么活动,上下文都不会消失。
                    【解决方案15】:

                    一个想法是在您的主要活动中拥有一个静态变量,实例化为包名称。然后只需引用该变量。

                    您必须在主活动的onCreate() 方法中对其进行初始化:

                    类全局:

                    public static String PACKAGE_NAME;
                    

                    那么..

                    @Override
                    public void onCreate(Bundle savedInstanceState) {
                        super.onCreate(savedInstanceState);
                        setContentView(R.layout.main);
                    
                        PACKAGE_NAME = getApplicationContext().getPackageName();
                    }
                    

                    然后您可以通过Main.PACKAGE_NAME 访问它。

                    【讨论】:

                    • 这对我来说似乎是目前最实用的解决方案,但它确实需要我创建活动的子类...暂时 +1。
                    • 我的理解是final 使其不可变,可初始化仅在构造函数中并且仅一次onCreate() 不是构造函数。如有错误请指正。
                    • 这种方法不正确。例如,如果您的应用程序在您进行次要活动时进入后台,然后又恢复。您的主要活动的 onCreate() 无法调用,您的 PACKAGE_NAME 将为空!此外,如果您的应用程序有 10 个入口点并且没有明确的“主要活动”怎么办?您可以在这个问题上查看我的答案以了解正确的方法
                    • @JohnLeehey,如果应用程序进入后台,Android 系统可能会在某个时候终止该进程,从而导致静态变量被重置。由于这种行为,我在 Android 中遇到了一些问题,因此尝试仅使用静态变量来存储非持久性数据。
                    • @Turbo,如果 Android 杀死进程,onCreate 无论如何都必须再次调用,所以这个解决方案应该没有问题。
                    猜你喜欢
                    • 2012-03-15
                    • 2023-03-17
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-07-30
                    • 2015-02-23
                    • 2020-10-09
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多