Android Wear 应用程序无法通过手机安装 [英] Android Wear app not installing through handset

查看:34
本文介绍了Android Wear 应用程序无法通过手机安装的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 此处 但它不起作用.该 apk 从未安装到可穿戴设备上.这是 logcat 输出:

I'm trying to get a wearable app installed through an Android handset using the 'Package with Android Studio method' found here but it's not working. The apk is never installed to the wearable device. This is the logcat output:

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

作为旁注,我可以手动打包(也在上面的链接中进行了描述),并且当我在手机上运行它时,apk 会安装在可穿戴设备上.我正在使用 buildToolsVersion 20.0.0,我正在运行 Android Studio 0.8.2 并且在我的手机模块的 build.gradle 中有这一行:

As a side note I am able to package manually (also described in the link above) and the apk gets installed on the wearable device when I run it on the handset. I am using buildToolsVersion 20.0.0, I'm running Android Studio 0.8.2 and have this line in my handset module's build.gradle:

wearApp project(':wearable')

我已经没有关于如何调试的想法了,日志似乎毫无用处.有什么想法吗?

I've run out of ideas on how to debug this, the logs seem pretty useless. Any ideas?

将针对手机和可穿戴模块发布 Manifest 和 build.gradle 的相关部分.

Going to post relevant sections of Manifest and build.gradle for both the handset and wearable module.

手机清单

<?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>

手机 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"
}

可穿戴清单

<?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

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.+'
}

推荐答案

要特别回答@odiggity,在手机应用程序的build.gradle 文件中,您应该提及的确切名称磨损应用文件夹.如果您在 Android Studio 中创建了该项目,那么您的 build.gradle 应如下所示:

To Answer @odiggity specifically, in build.gradle file of your phone app, you should mention the exact name of the wear app folder. If you created the project in Android Studio, then your build.gradle should look like this:

                      wearApp project(':wear')

发生这种情况的原因如下:

This can happen because of the following reasons:

  • 磨损&移动应用的权限" 不同(Wear 应用权限应该是移动应用权限的一个子集).
  • Wear & Mobile app's "permissions" are not same (Wear App permissions should be a subset of Mobile App permissions).

这在开发者网站上的任何地方都没有记录,但是我根据我的个人经验发现了这一点.我能想到的这个限制背后的原因是,谷歌想要防止偷偷摸摸的开发者利用用户&他们的隐私.

This is not documented anywhere on developers website, however I found this with my personal experience. The reason I can think of behind this restriction is, Google want to prevent sneaky developers to exploit users & their privacy.

    Wear & 的
  • 包名移动应用不匹配.
  • VersionNumber &Wear & 的 VersionName移动应用不匹配
  • Application ID (build.gradle file) of Mobile &穿戴应用不匹配.
  • 默认情况下,可穿戴包仅包含在 release 版本中
  • 两个应用程序必须签名使用相同的密钥
  • 从 Android Studio 3.0 开始,使用 run 创建的 apk 构建是仅测试构建,不允许在穿戴时安装(返回代码 -15,请参阅 此信息)
  • 资产压缩
  • Package name of Wear & Mobile apps are not matching.
  • VersionNumber & VersionName of both Wear & Mobile app not matching
  • Application ID (build.gradle file) of Mobile & wear app are not matching.
  • by default wearable packages are only included in release builds
  • both apps must be signed with the same key
  • as of Android Studio 3.0 apk builds created with run are test only builds that don't allow installation on wear (returnCode -15, see this information)
  • Asset Compression

如果您使用 Eclipse 进行开发,请确保关闭资产压缩",否则原始文件夹中的.apk"文件将被双重压缩 &手机将无法识别移动应用是否打包了 Wear 应用.

If you are using Eclipse for development, make sure you turn off the "Asset Compression" otherwise the ".apk" file in raw folder will get double compressed & the phone won't be able to recognize if the Mobile app is packaging wear app or not.

最佳解决方案:

使用 Android Studio.

  1. 创建安卓项目
  2. 选择电话和穿搭项目
  3. 按照项目创建步骤操作
  4. 将 Wear 应用中使用的所有权限复制到移动应用的清单中,反之亦然

调试

当您在可穿戴设备上找不到 Wear 应用时,您可以随时查看两台设备的日志以了解发生了什么.您可以过滤 WearablePkgInstaller 以查找与可穿戴包安装相关的所有日志记录.

When you don't find the wear app on the wearable you can always look into logs of both devices to see what is going on. You can filter on WearablePkgInstaller to find all logging related to wearable package installation.

从您设备上的 Wear OS 应用触发高级设置"中的重新同步应用"选项并检查日志.仅为您的应用同步可穿戴设备的另一种方法是重新安装您的应用.届时,可穿戴设备也会与您的包裹同步.

From the Wear OS app on you device trigger the "resync apps" option from "advanced settings" and check the logs. Alternative way to sync only the wearable for your app is to reinstall your app. At that point the wearable is also synced for your package.

设备日志应该列出如下内容:

Device logging should list something like:

11-07 14:58:53.127 3330-8739/? I/WearablePkgInstaller: Setting DataItem to install wearable apps for com.spotify.music

com.spotify.music 是您的应用程序 ID.这只是 Spotify 的一个例子.

With com.spotify.music being your app Id. This is just an example for Spotify.

在手表上(通过蓝牙或 USB 调试),您可以找到使用相同过滤器显示问题或成功的日志:

And on the watch (debug over bluetooth or USB) you can find logging with this same filter showing issues or success:

11-07 15:00:02.533 1032-1048/? I/WearablePkgInstaller: Package com.spotify.music was installed.

大多数错误消息都是不言自明的.您可以在 WearPackageInstallerService 类的源代码.然而,有些只是一个返回码.对于这些返回代码,请检查 这个 PackageManager 源代码.

Most error messages are self explanatory. You can find many examples of these errors in the source code of WearPackageInstallerService class. Some however are just a returnCode. For these return codes check the values in this PackageManager source code.

这篇关于Android Wear 应用程序无法通过手机安装的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆