¿Cómo obtener el nombre del paquete desde cualquier lugar?

346

Soy consciente de la disponibilidad de Context.getApplicationContext () y View.getContext () , a través del cual puedo llamar a Context.getPackageName () para recuperar el nombre del paquete de una aplicación.

Funcionan si llamo desde un método para el cual a Viewo un Activityobjeto está disponible, pero si quiero encontrar el nombre del paquete desde una clase totalmente independiente con no Viewo Activity, ¿hay alguna manera de hacerlo (directa o indirectamente)?

ef2011
fuente
77
La respuesta aceptada ocasionará que su aplicación ocasionalmente se CRASH: lea los comentarios de AddDev y Turbo y gracias a ambos por sugerir soluciones.
nikib3ro
1
Es posible que no tenga otra opción, pero como práctica recomendada, diría que es mejor pasar esto a la clase en la que lo necesita desde su último punto de Contexto de alguna manera. Está accediendo a información de contexto de tiempo de ejecución desde una clase que no conoce los Contextos de forma estática, me huele mal. Otro enfoque sería codificarlo en alguna parte.
Adam

Respuestas:

488

Una idea es tener una variable estática en su actividad principal, instanciada para ser el nombre del paquete. Entonces solo haga referencia a esa variable.

Tendrá que inicializarlo en el onCreate()método de la actividad principal :

Global a la clase:

public static String PACKAGE_NAME;

Entonces..

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

    PACKAGE_NAME = getApplicationContext().getPackageName();
}

Luego puede acceder a través de Main.PACKAGE_NAME.

John Leehey
fuente
3
Esta parece la solución más práctica para mí en este momento, pero sí me obliga a crear una subclase de la actividad ... +1 por ahora.
ef2011
1
Acabo de encontrar una referencia similar: stackoverflow.com/questions/2002288/…
ef2011
13
Entiendo que lo finalhace inmutable, inicializable solo en un constructor y solo una vez . onCreate()No es un constructor. Corrija si me equivoco.
ef2011
79
Este enfoque es incorrecto. Por ejemplo, si su aplicación pasa a segundo plano cuando está en una actividad secundaria y luego se restaura. No se pudo llamar al onCreate () de su actividad principal y su PACKAGE_NAME será nulo. Además, ¿qué pasa si su aplicación tiene 10 puntos de entrada y no hay una "actividad principal" clara? Puede verificar mi respuesta en esta pregunta para el enfoque correcto
Addev
3
@Turbo, si Android mata el proceso, onCreatetendrá que volver a llamarse de todos modos, por lo que esta solución aún no debería ser un problema.
John Leehey
276

Si usa el complemento gradle-android-para construir su aplicación, entonces puede usar

BuildConfig.APPLICATION_ID

para recuperar el nombre del paquete desde cualquier ámbito, incl. uno estático

Billda
fuente
23
Esa es la forma correcta, debe ser la respuesta aceptada.
aberaud
44
Nota: Con las compilaciones de múltiples versiones, esto devolverá (dependiendo de la importación utilizada para obtener acceso a la clase BuildConfig) el nombre del paquete de la configuración predeterminada, no el nombre del paquete de la versión.
Rolf ツ
2
@Rolf ツ Eso no es cierto, devolverá el nombre del paquete correcto de la aplicación;) tal vez lo esté confundiendo con el nombre del paquete de sus clases de Java
Billda
28
Tenga cuidado si usa esto en un proyecto de biblioteca, esto no funcionará.
zyamys
66
Tenga cuidado si también usa esto en múltiples módulos dentro de un proyecto.
user802421
68

Si con la palabra "en cualquier lugar" quiere decir sin tener un explícito Context(por ejemplo, de un hilo de fondo) debe definir una clase en su proyecto como:

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

Luego, en su manifestnecesita agregar esta clase al Namecampo en la Applicationpestaña. O edite el xml y ponga

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

y luego desde cualquier lugar al que puedas llamar

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

Espero eso ayude.

Addev
fuente
Esto no es seguro para subprocesos, pero probablemente pueda salirse con la suya si el subproceso de fondo se inicia con esta actividad más adelante.
tomwhipple
3
Es seguro para subprocesos ya que la referencia a la instancia es lo primero que se establece cuando se inicia la aplicación
Addev
17
Según este problema: code.google.com/p/android/issues/detail?id=8727 Los objetos ContentProvider se crean antes del objeto Aplicación, aparentemente contraria a la documentación, pero también aparentemente según el diseño. Esto podría provocar que su instancia aún no se establezca si se llama a getInstance () durante la inicialización de ContentProvider.
Carl
3
La documentación Application.onCreate()se ha modificado para reflejar esto: ahora declara específicamente "Llamado cuando la aplicación se está iniciando, antes de cualquier actividad, servicio u objeto receptor (excluyendo proveedores de contenido)".
Paul Lammertsma
2
Esta debería ser la respuesta seleccionada, porque el contexto nunca desaparecerá sin importar qué actividad se esté ejecutando.
Elad Nava
43

Si usa Gradle Build, use esto: BuildConfig.APPLICATION_IDpara obtener el nombre del paquete de la aplicación.

Mahendra Liya
fuente
66
El ID de la aplicación y el nombre del paquete son cosas diferentes. El ID de la aplicación se define a través del archivo gradle.build, y el nombre del paquete se define en el Manifiesto. Si bien a menudo tienen el mismo valor, a menudo también difieren, en escenarios de compilación más complejos. Se pueden asignar diferentes ID de aplicaciones a diferentes configuraciones de compilación mientras el nombre del paquete permanece sin cambios.
Uli
3
@Uli Para aquellos que quieran conocer los matices con un poco más de detalle tools.android.com/tech-docs/new-build-system/…
Kevin Lee
10
@Uli Dicho esto, incluso si el applicationId en app.gradle difiere del packageName dentro de AndroidManifest.xml, llamando a context.getPackageName () devuelve el applicationId y no el packageName dentro de AndroidManifest.xml. El objetivo del nuevo sistema de compilación era desacoplar ambos, por lo que applicationId es el nombre real del paquete de la aplicación conocido por Google Play y para el dispositivo en el que está instalado; no puede cambiar después de la implementación. Mi punto es que está bien usar BuildConfig.APPLICATION_ID. Avíseme si me equivoco (:
Kevin Lee
2
@kevinze ¡Completamente preciso! Hice una prueba para verificar dos veces. Gracias por la aclaración / corrección.
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;

}
bala7s
fuente
4

Puede obtener el nombre de su paquete de esta manera:

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

Aquí están las opciones:

$ 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.
usuario8128167
fuente
3

Puede usar el método no documentadoandroid.app.ActivityThread.currentPackageName() :

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

Advertencia: Esto debe hacerse en el hilo principal de la aplicación.

Gracias a esta publicación de blog por la idea: http://blog.javia.org/static-the-android-application-package/ .

Alexei Khlebnikov
fuente
2

Para aquellos que usan Gradle, como mencionó @Billda, puede obtener el nombre del paquete a través de:

BuildConfig.APPLICATION_ID

Esto le da el nombre del paquete declarado en su aplicación gradle:

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

Si está interesado en obtener el nombre del paquete utilizado por sus clases de Java (que a veces es diferente de applicationId), puede usar

BuildConfig.class.getPackage().toString()

Si no está seguro de cuál usar, lea aquí :

Nota: El ID de la aplicación solía estar directamente relacionado con el nombre del paquete de su código; por lo que algunas API de Android usan el término "nombre del paquete" en los nombres de sus métodos y nombres de parámetros, pero en realidad esta es la ID de su aplicación. Por ejemplo, el método Context.getPackageName () devuelve su ID de aplicación. No es necesario compartir el verdadero nombre del paquete de su código fuera del código de su aplicación.

usuario1506104
fuente
¿Qué código usaste? proporcione el error exacto que recibió.
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; 

Espero que funcione.

Juboraj Sarker
fuente
0

Cree un módulo java para que se ejecute inicialmente al iniciar su aplicación. Este módulo ampliará la clase de aplicación de Android e inicializará cualquier variable de aplicación global y también contendrá rutinas de utilidad para toda la aplicación:

public class MyApplicationName extends Application {

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

    public String getPackageName() { return PACKAGE_NAME; }
}

Por supuesto, esto podría incluir lógica para obtener el nombre del paquete del sistema Android; Sin embargo, lo anterior es un código más pequeño, más rápido y más limpio que obtenerlo de Android.

Asegúrese de colocar una entrada en su archivo AndroidManifest.xml para indicarle a Android que ejecute su módulo de aplicación antes de ejecutar cualquier actividad:

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

Luego, para obtener el nombre del paquete desde cualquier otro módulo, ingrese

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

El uso de un módulo de aplicación también le brinda un contexto para los módulos que necesitan pero no tienen un contexto.

Earl Allen
fuente
0

Use: BuildConfig.APPLICATION_ID para obtener el NOMBRE DEL PAQUETE en cualquier lugar (es decir, servicios, receptor, actividad, fragmento, etc.)

Ejemplo: String PackageName = BuildConfig.APPLICATION_ID;

pharid
fuente
0

Solo importa Android.app, luego puedes usar: <br/>Application.getProcessName()<br/>

Obtenga el nombre del proceso de aplicación actual sin contexto, vista o actividad.

intitulado
fuente