简体   繁体   English

Android Wear应用程序无法通过手机安装

[英]Android Wear app not installing through handset

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. 我正在尝试通过Android手机安装可穿戴应用程序,使用此处找到的“使用Android Studio方法打包” 但它无效。 The apk is never installed to the wearable device. apk永远不会安装到可穿戴设备上。 This is the logcat output: 这是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) }

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. 作为旁注,我能够手动打包(也在上面的链接中描述),当我在手机上运行时,apk安装在可穿戴设备上。 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: 我正在使用buildToolsVersion 20.0.0,我正在运行Android Studio 0.8.2并且在我的手机模块的build.gradle中有这一行:

wearApp project(':wearable')

I've run out of ideas on how to debug this, the logs seem pretty useless. 我已经没有关于如何调试它的想法,日志似乎没用。 Any ideas? 有任何想法吗?

EDIT: Going to post relevant sections of Manifest and build.gradle for both the handset and wearable module. 编辑:发布手机和可穿戴模块的Manifest和build.gradle的相关部分。

Handset Manifest 手机清单

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

Handset build.gradle 手机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"
}

Wearable Manifest 可穿戴的舱单

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

Wearable build.gradle 可穿戴的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.+'
}

To Answer @odiggity specifically, in build.gradle file of your phone app, you should mention the exact name of the wear app folder . 要特别回答@odiggity,在手机应用程序的build.gradle文件中,您应该提到wear app文件夹确切名称 If you created the project in Android Studio , then your build.gradle should look like this: 如果您在Android Studio中创建了项目,那么您的build.gradle应如下所示:

                      wearApp project(':wear')

This can happen because of the following reasons: 这可能是由于以下原因:

  • Wear & Mobile app's "permissions" are not same (Wear App permissions should be a subset of Mobile App permissions). Wear&Mobile应用程序的"permissions"不相同(Wear App权限应该是Mobile App权限的子集)。

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. 我可以想到这个限制背后的原因是,谷歌希望防止偷偷摸摸的开发者利用用户及其隐私。

  • Package name of Wear & Mobile apps are not matching. Wear和Mobile应用程序的Package name不匹配。
  • VersionNumber & VersionName of both Wear & Mobile app not matching Wear&Mobile应用程序的VersionNumberVersionName不匹配
  • Application ID (build.gradle file) of Mobile & wear app are not matching. Mobile&wear app的Application ID (build.gradle文件)不匹配。
  • by default wearable packages are only included in release builds 默认情况下,可穿戴软件包仅包含在release版本中
  • both apps must be signed with the same key 两个应用必须使用相同的密钥signed
  • 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 ) 从Android Studio 3.0开始,使用run创建的apk版本是test only builds ,不允许在佩戴时安装(returnCode -15,请参阅此信息
  • Asset Compression 资产压缩

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. 如果您使用Eclipse进行开发,请确保关闭“资产压缩”,否则原始文件夹中的“.apk”文件将被double compressed ,并且phone won't be able to recognize移动应用程序是否包装磨损应用程序或不。

Best Solution: 最佳方案:

Use Android Studio. 使用Android Studio。

  1. Create Android Project 创建Android项目
  2. Select Phone & Wear project 选择手机和磨损项目
  3. Follow the steps for project creation 按照项目创建的步骤进行操作
  4. Copy all the permissions used in Wear app to Mobile app's Manifest or vice versa 将Wear应用程序中使用的所有权限复制到Mobile app的Manifest,反之亦然

Debugging 调试

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. 您可以对WearablePkgInstaller进行过滤,以查找与可穿戴软件包安装相关的所有日志记录。

From the Wear OS app on you device trigger the "resync apps" option from "advanced settings" and check the logs. 从您设备上的Wear OS应用程序中触发“高级设置”中的“重新同步应用程序”选项并检查日志。 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

With com.spotify.music being your app Id. 使用com.spotify.music作为您的应用ID。 This is just an example for Spotify. 这只是Spotify的一个例子。

And on the watch (debug over bluetooth or USB) you can find logging with this same filter showing issues or success: 在手表上(通过蓝牙或USB调试),您可以使用相同的过滤器查找记录问题或成功的日志记录:

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

Most error messages are self explanatory. 大多数错误消息都是自解释的。 You can find many examples of these errors in the source code of WearPackageInstallerService class . 您可以在WearPackageInstallerService类的源代码中找到许多这些错误的示例。 Some however are just a returnCode. 然而,有些只是一个returnCode。 For these return codes check the values in this PackageManager source code . 对于这些返回代码,请检查此PackageManager源代码中的值。

I had ussue with wear product flavors . 我有穿着产品口味的问题 I had flavors in both handheld and wear apps. 我在手持和磨损应用程序中都有口味。 To solve my issue I used next code in build.gradle handheld app file: 为了解决我的问题,我在build.gradle手持设备app文件中使用了下一个代码:

freeWearApp project(path: ':wear', configuration: 'wearfreeRelease')
fullWearApp project(path: ':wear', configuration: 'wearfullRelease')

where, free and full are flavors from handheld module, wearfree and wearfull are flavors from wear mudule, Release is name of wear module buildtype. 其中, 自由充分 从手持模块,wearfreewearfull口味的磨损mudule口味, 发行是磨损模块buildtype的名称。

And don't forget publishNonDefault true in the android block of the wear gradle. 而且不要忘记 publishNonDefault true在的gradle磨损了Android块。

I had this problem even after checking the package names, application IDs, and making sure the wear module didn't have any permissions that the handheld module didn't. 即使在检查包名称,应用程序ID并确保磨损模块没有掌上电脑模块没有的任何权限之后,我也遇到了这个问题。

My problem was that I was requesting the permission android.permission.BIND_NOTIFICATION_LISTENER_SERVICE in AndroidManifest.xml for the wearable module. 我的问题是我在AndroidManifest.xml中为可穿戴模块请求了android.permission.BIND_NOTIFICATION_LISTENER_SERVICE权限。 It seems that this should only be requested for the handheld module. 似乎只应该为手持模块请求。

据我所知,目前不支持产品口味,要么使用手动构建(资产或原始),要么删除产品口味。

From my experience it only works when building a signed release build. 根据我的经验,它只适用于构建签名版本构建时。 When deploying a debug build it never installed the wear app for me. 在部署调试版本时,它从未为我安装过磨损应用程序。 With signed release it worked with buildToolsVersion "19.1.0". 使用签名版本,它与buildToolsVersion“19.1.0”一起使用。

In this specific case I can see that you are using "compile project(':GooglePlay')". 在这个特定的情况下,我可以看到你正在使用“编译项目(':GooglePlay')”。 Is that the latest version? 那是最新版本吗? (compile 'com.google.android.gms:play-services-wearable:+') (编译'com.google.android.gms:play-services-wearable:+')

I've been having this issue recently, and in the end the following fixed it; 我最近一直在讨论这个问题,最后修复了这个问题;

  • Uninstall previous app 卸载以前的应用
  • Restart Phone 重启电话
  • Restart wear 重启磨损
  • Disconnect and reconnect wear 断开并重新连接磨损
  • Re-Sync apps in Android Wear application 在Android Wear应用程序中重新同步应用程序

And then it popped up on the watch. 然后它突然出现在手表上。 Before this I tried everything and was convinced the build was not working right 在此之前,我尝试了一切,并确信构建不正常

Just wanted to add something that I haven't seen in many answers. 只想添加一些我在许多答案中没有看到的内容。

You have to match the applicationId in your handheld app and wear app. 您必须匹配掌上电脑应用applicationId中的applicationId并佩戴应用程序。

I previously thought that you needed to have <uses-feature android:name="android.hardware.type.watch" /> in both the handheld and watch manifest, with add: android:required="true" for the wearable manifest and android:required="false" for the device. 我之前认为你需要在掌上电脑和监视清单中<uses-feature android:name="android.hardware.type.watch" /> ,并为可穿戴清单添加: android:required="true" android:required="false"表示设备。

THIS IS FALSE. 这是假的。 You do not need the above in the handheld manifest. 您在手持设备清单中不需要上述内容。 In fact with Wear 2.0 coming up Google has made some changes that will not allow you to upload any apk with minSdk lower than 23 if <uses-feature android:name="android.hardware.type.watch" /> is in your handheld app. 事实上,随着Wear 2.0即将推出,Google已经做了一些更改,如果在您的掌上电脑中<uses-feature android:name="android.hardware.type.watch" /> ,则无法上传任何minSdk低于23的apk应用程序。 Sorry for any confusion. 对不起任何困惑。

Got the same problem, it turned out that newrelic is instrumenting the Android Wear App. 遇到同样的问题,结果发现newrelic正在使用Android Wear App。 Try to comment the line: // apply plugin: 'newrelic' 尝试评论一下:// apply plugin:'newrelic'

I couldn't find a way to tell newrelic to keep away from the the wear app... 我找不到告诉newrelic远离磨损应用程序的方法......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM