android - reloj - instalar aplicaciones en smartwatch chino
La aplicación Android Wear no se instala a través del teléfono (8)
Desde mi experiencia, solo funciona cuando se construye una versión de lanzamiento firmada. Al implementar una versión de depuración, nunca instaló la aplicación de desgaste para mí. Con el lanzamiento firmado funcionó con buildToolsVersion "19.1.0".
En este caso específico puedo ver que está utilizando "compilar proyecto ('': GooglePlay'')". ¿Es esa la última versión? (compile ''com.google.android.gms: play-services-wearable: +'')
Estoy tratando de instalar una aplicación portátil a través de un teléfono Android utilizando el método ''Paquete con estudio de Android'' que se encuentra here pero no funciona. El apk nunca se instala en el dispositivo portátil. Esta es la salida logcat:
07-28 15:11:54.107 766-820/? W/PackageManager﹕ Unknown permission com.google.android.wearable.READ_SETTINGS in package com.google.android.gms
07-28 15:11:54.117 766-820/? W/PackageManager﹕ Not granting permission com.google.android.gm.permission.AUTO_SEND to package com.google.android.wearable.app (protectionLevel=2 flags=0x88be44)
07-28 15:11:54.117 766-820/? W/PackageManager﹕ Not granting permission android.permission.MEDIA_CONTENT_CONTROL to package com.google.android.wearable.app (protectionLevel=18 flags=0x88be44)
07-28 15:11:55.047 632-632/? D/WearablePkgInstaller﹕ Got PackageUpdateReceiver message Intent { act=android.intent.action.PACKAGE_REMOVED dat=package:my.package.name flg=0x4000010 cmp=com.google.android.wearable.app/com.google.android.clockwork.companion.packagemanager.PackageUpdateReceiver (has extras) }
07-28 15:11:55.177 632-632/? D/WearablePkgInstaller﹕ Got PackageUpdateReceiver message Intent { act=android.intent.action.PACKAGE_ADDED dat=package:my.package.name flg=0x4000010 cmp=com.google.android.wearable.app/com.google.android.clockwork.companion.packagemanager.PackageUpdateReceiver (has extras) }
Como nota al margen, puedo empaquetar manualmente (también descrito en el enlace anterior) y la aplicación se instala en el dispositivo portátil cuando lo ejecuto en el teléfono. Estoy usando buildToolsVersion 20.0.0, ejecuto Android Studio 0.8.2 y tengo esta línea en el build.gradle de mi módulo de teléfono:
wearApp project('':wearable'')
Me he quedado sin ideas sobre cómo depurar esto, los registros parecen bastante inútiles. ¿Algunas ideas?
EDITAR: irá a publicar secciones relevantes de Manifest y build.gradle para el teléfono y el módulo portátil.
Manifiesto del auricular
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.package.name"
android:installLocation="auto"
android:versionCode="259"
android:versionName="4.6.1">
<!-- =========== -->
<!-- PERMISSIONS -->
<!-- =========== -->
<permission
android:name="my.app.name.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- ====================== -->
<!-- APPLICATION PROPERTIES -->
<!-- ====================== -->
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="19" />
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:xlargeScreens="true"/>
<application
android:name=".AppState"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.MyApp"
android:hardwareAccelerated="true">
<!-- ==================== -->
<!-- GOOGLE PLAY SERVICES -->
<!-- ==================== -->
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<!-- ================== -->
<!-- Android Wear -->
<!-- ================== -->
<service
android:name=".wear.DataLayerListenerService" >
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
<!-- This is used for manual packaging I have this commented out when -->
<!-- packaging with Android Studio-->
<!--<meta-data android:name="com.google.android.wearable.beta.app"-->
<!--android:resource="@xml/wearable_app_desc"/>-->
...The rest of the activities
</application>
</manifest>
Auricular build.gradle
buildscript {
repositories {
maven { url ''http://download.crashlytics.com/maven'' }
}
dependencies {
}
}
apply plugin: ''com.android.application''
apply plugin: ''crashlytics''
apply plugin: ''newrelic''
repositories {
mavenCentral()
maven { url ''http://download.crashlytics.com/maven'' }
}
dependencies {
compile fileTree(dir: ''libs'', include: ''*.jar'')
compile ''com.android.support:support-v4:20.0.+''
compile ''com.android.support:appcompat-v7:20.0.+''
compile project('':facebook'')
compile project('':mopub-sdk'')
compile project('':GooglePlay'')
compile ''com.newrelic.agent.android:android-agent:3.+''
compile ''com.crashlytics.android:crashlytics:1.+''
androidTestCompile fileTree(dir: ''tests/libs'', include: ''*.jar'')
wearApp project('':wearable'')
}
android {
compileSdkVersion 19
buildToolsVersion ''20.0.0''
//Build type is debug to avoid conflict with Proguard
testBuildType = "debug"
defaultConfig {
testApplicationId "my.package.name.test"
testInstrumentationRunner "com.zutubi.android.junitreport.JUnitReportTestRunner"
}
lintOptions {
// We do not want to abort the build due to lint errors
abortOnError false
}
sourceSets {
// Main is the default unless stated otherwise
main {
manifest.srcFile ''AndroidManifest.xml''
java.srcDirs = [''src'']
resources.srcDirs = [''src'']
aidl.srcDirs = [''src'']
renderscript.srcDirs = [''src'']
res.srcDirs = [''res'']
assets.srcDirs = [''assets'']
}
// Testing
androidTest.setRoot(''tests'')
androidTest {
java.srcDirs = [''tests/src'']
res.srcDirs = [''tests/res'']
}
// Cannot add beta icons in here because custom flavour source sets are created
// during compilation and name duplication will result in a crash
}
signingConfigs {
debug {
storeFile file("**")
storePassword "***"
keyAlias "***"
keyPassword "***"
}
release {
storeFile file("***")
storePassword "***"
keyAlias "***"
keyPassword "***"
}
}
buildTypes {
// Development configuration
debug {
debuggable true
jniDebugBuild true
signingConfig signingConfigs.debug
runProguard false
}
// Release configuration
release {
debuggable false
jniDebugBuild false
signingConfig signingConfigs.release
// COMMENTED PROGUARD OUT FOR NOW TO SEE IF IT WILL HELP
// // Configure ProGuard
// runProguard true
// // General configuration
// proguardFile ''proguard/proguard.cfg''
// // Add all of our component-specific configurations (excluding the Android generic, as we want it to be last)
// FileTree tree = fileTree(dir: ''proguard'', include: ''*.txt'', exclude: ''Android.txt'')
// tree.each {File file ->
// proguardFile file.getCanonicalPath()
// }
// // Add a fallback configuration for all Android apps
// proguardFile ''proguard/Android.txt''
}
// Release configuration, but debuggable and without ProGuard
// Used for testing features like G+ and in-app billing where a release config is required
staging {
debuggable true
jniDebugBuild true
signingConfig signingConfigs.release
runProguard false
}
}
productFlavors {
production {
applicationId "my.package.name"
}
internalBeta {
applicationId "my.internalbetapackage.name"
// Beta icons
sourceSets.internalBeta.res.srcDirs = [''res-beta/internal'']
}
externalBeta {
applicationId "my.externalbetapackage.name"
// Beta icons
sourceSets.externalBeta.res.srcDirs = [''res-beta/external'']
}
testing{
applicationId "my.package.name"
}
}
// Without this, gradle will complain that duplicate files were added to the APK, see:
// http://stackoverflow.com/questions/20673888/duplicate-files-copied-android-studio-0-4-0
packagingOptions {
exclude ''META-INF/LICENSE.txt'' // twitter4j
exclude ''META-INF/ASL2.0'' // jackson
exclude ''META-INF/LICENSE'' // jackson
exclude ''META-INF/NOTICE'' // jackson
}
}
task makeTestApks {
dependsOn "assembleProductionRelease"
dependsOn "assembleProductionTest"
}
Manifiesto usable
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.package.name">
<uses-feature android:name="android.hardware.type.watch" android:required="false"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault" >
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name=".WearReaderActivity"
android:label="MyApp" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="my.package.name.READ"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".wear.DataLayerListenerService" >
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
</application>
</manifest>
Build.gradle usable
repositories {
mavenCentral()
}
apply plugin: ''com.android.application''
apply plugin: ''newrelic''
android {
compileSdkVersion 19
buildToolsVersion ''20.0.0''
defaultConfig {
minSdkVersion 19
targetSdkVersion 19
versionCode 259
versionName "4.6.1"
}
signingConfigs {
debug {
keyAlias ''***''
keyPassword ''***''
storeFile file(''sameAsHandset/debug.keystore'')
storePassword ''***''
}
release {
storeFile file("sameAsHandset/android.keystore")
storePassword "***"
keyAlias "***"
keyPassword "***"
}
}
buildTypes {
release {
debuggable true
jniDebugBuild false
signingConfig signingConfigs.release
}
}
productFlavors {
production {
applicationId "my.package.name"
}
internalBeta {
applicationId "my.internalBetaPackage.name"
// Beta icons
sourceSets.internalBeta.res.srcDirs = [''res-beta/internal'']
}
externalBeta {
applicationId "my.externalBetaPackage.name"
// Beta icons
sourceSets.externalBeta.res.srcDirs = [''res-beta/external'']
}
testing{
applicationId "my.package.name"
}
}
}
dependencies {
compile fileTree(dir: ''libs'', include: [''*.jar''])
compile project('':GooglePlay'')
compile ''com.newrelic.agent.android:android-agent:3.+''
}
He tenido este problema recientemente, y al final lo siguiente lo solucionó;
- Desinstalar la aplicación anterior
- Reiniciar el teléfono
- Desgaste de reinicio
- Desconecta y reconecta el desgaste
- Re-sincronización de aplicaciones en la aplicación Android Wear
Y luego apareció en el reloj. Antes de esto probé todo y estaba convencido de que la construcción no funcionaba bien
Para responder a @odiggity específicamente, en el archivo build.gradle de la aplicación de su teléfono, debe mencionar el nombre exacto de la carpeta de la aplicación de desgaste . Si creó el proyecto en Android Studio , su build.gradle debería tener este aspecto:
wearApp project('':wear'')
Esto puede suceder debido a las siguientes razones:
- Los
"permissions"
la aplicación Wear & Mobile no son los mismos (los permisos de la aplicación Wear deben ser un subconjunto de los permisos de la aplicación Mobile).
Esto no está documentado en ninguna parte del sitio web de los desarrolladores, sin embargo, encontré esto con mi experiencia personal. La razón por la que puedo pensar detrás de esta restricción es que Google quiere evitar que los desarrolladores astutos exploten a los usuarios y su privacidad.
-
Package name
delPackage name
de aplicaciones Wear & Mobile no coincide. -
VersionNumber
yVersionName
de la aplicación Wear y Mobile no coinciden -
Application ID
(archivo build.gradle) de la aplicación Mobile & wear no coincide. - por defecto, los paquetes portátiles solo se incluyen en las
release
derelease
- Ambas aplicaciones deben estar
signed
con la misma clave. - a partir de Android Studio 3.0 las compilaciones de apk creadas con ejecución son
test only builds
que no permiten la instalación en uso (returnCode -15, consulte esta información ) - Compresión de activos
Si está utilizando Eclipse para el desarrollo, asegúrese de desactivar "Compresión de activos"; de lo contrario, el archivo ".apk" en la carpeta sin formato se double compressed
y el phone won''t be able to recognize
si la aplicación móvil está empaquetando. o no.
Mejor solución:
Usa Android Studio.
- Crear proyecto de Android
- Seleccione el proyecto Phone & Wear
- Siga los pasos para la creación del proyecto.
- Copie todos los permisos utilizados en la aplicación Wear al manifiesto de la aplicación móvil o viceversa.
Depuración
Cuando no encuentra la aplicación de desgaste en el dispositivo portátil, siempre puede mirar los registros de ambos dispositivos para ver qué está pasando. Puede filtrar en WearablePkgInstaller
para encontrar todo el registro relacionado con la instalación del paquete wearable.
Desde la aplicación Wear OS en su dispositivo, active la opción "resincronizar aplicaciones" desde "configuración avanzada" y verifique los registros. Una forma alternativa de sincronizar solo el wearable para su aplicación es reinstalarla. En ese momento, el dispositivo también se sincroniza para su paquete.
El registro del dispositivo debería incluir algo como:
11-07 14:58:53.127 3330-8739/? I/WearablePkgInstaller: Setting DataItem to install wearable apps for com.spotify.music
Con com.spotify.music siendo tu ID de aplicación. Este es solo un ejemplo para Spotify.
Y en el reloj (depuración a través de bluetooth o USB) puede encontrar el registro con este mismo filtro que muestra problemas o éxito:
11-07 15:00:02.533 1032-1048/? I/WearablePkgInstaller: Package com.spotify.music was installed.
La mayoría de los mensajes de error son auto explicativos. Puede encontrar muchos ejemplos de estos errores en el código fuente de la clase WearPackageInstallerService . Algunos, sin embargo, son sólo un código de retorno. Para estos códigos de retorno, verifique los valores en este código fuente de PackageManager .
Por lo que sé, los sabores de productos no son compatibles en este momento, ya sea utilizando la compilación manual (activo o en bruto) o elimine los sabores de productos.
Solo quería agregar algo que no he visto en muchas respuestas.
Debe coincidir con el applicationId
en su aplicación de mano y en la aplicación de desgaste.
Anteriormente pensé que necesitaba tener <uses-feature android:name="android.hardware.type.watch" />
tanto en el dispositivo portátil como en el manifiesto del reloj, con add: android:required="true"
para el manifiesto portátil y android:required="false"
para el dispositivo.
Esto es falso No necesita lo anterior en el manifiesto de mano. De hecho, con el lanzamiento de Wear 2.0, Google ha realizado algunos cambios que no le permitirán cargar ningún archivo apk con minSdk inferior a 23 si <uses-feature android:name="android.hardware.type.watch" />
está en su computadora de mano la aplicación Lo siento por cualquier confusión.
Teniendo el mismo problema, resultó que newrelic está instrumentando la aplicación Android Wear. Intenta comentar la línea: // aplicar el complemento: ''newrelic''
No pude encontrar una manera de decirle a newrelic que se mantenga alejado de la aplicación de desgaste ...
Tuve este problema incluso después de verificar los nombres de los paquetes, las ID de las aplicaciones y asegurarme de que el módulo de desgaste no tuviera ningún permiso que el módulo de mano no tenía.
Mi problema fue que estaba solicitando el permiso android.permission.BIND_NOTIFICATION_LISTENER_SERVICE
en AndroidManifest.xml para el módulo portátil. Parece que esto solo debe solicitarse para el módulo de mano.
Tuve problemas con los sabores del producto . Tenía sabores tanto en aplicaciones de mano como de desgaste. Para resolver mi problema, utilicé el siguiente código en el archivo de la aplicación de computadora de mano build.gradle:
freeWearApp project(path: '':wear'', configuration: ''wearfreeRelease'')
fullWearApp project(path: '':wear'', configuration: ''wearfullRelease'')
donde, libre y completo son sabores del módulo de mano, sin desgaste y sin desgaste son sabores del desgaste mudule, Release es el nombre de construcción del módulo de desgaste.
Y no se olvide de publishNonDefault true
en el bloque de android del desgaste.