Search code examples
javaandroidvisual-studioxamarinxamarin.android

Xamarin Error only Android 6.0 Mono.AndroidTools.InstallFailedException and NSTALL_PARSE_FAILED_MANIFEST_MALFORMED


I created a project in Xamarin with Visual Studio Professional 2017, the project clean/build/compile normally and install on Android 7.0, 7.1, 8.0, 8.1 and 9.0 (emulator and devices).

compile and build ok

However, don't install/build on Android 6.0 and 6.1 (emulator or device), I try to install in the emulator and device, show the error:

install fail in android 6.0

1>C:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.25\\bin\keytool.exe -list -alias androiddebugkey -storepass android -keypass android -keystore "C:\Users\Claudio\AppData\Local\Xamarin\Mono for Android\debug.keystore" 
1>C:\Program Files (x86)\Android\android-sdk\build-tools\27.0.3\zipalign.exe 4 "C:\Workspace\htdocs\Projetos\aprepara-xamarin-raksha\Ishpia.Droid\obj\Debug\81\android\bin\com.bergmannsoft.aprepara.apk" "bin\Debug\\com.bergmannsoft.aprepara-Signed.apk" 
1>C:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.25\\bin\java.exe -jar "C:\Program Files (x86)\Android\android-sdk\build-tools\27.0.3\lib\apksigner.jar" sign --ks "C:\Users\Claudio\AppData\Local\Xamarin\Mono for Android\debug.keystore" --ks-pass pass:android --ks-key-alias androiddebugkey --key-pass pass:android --min-sdk-version 22 --max-sdk-version 27  C:\Workspace\htdocs\Projetos\aprepara-xamarin-raksha\Ishpia.Droid\bin\Debug\com.bergmannsoft.aprepara-Signed.apk 
1>ADB0000:  Deployment failed
1>Mono.AndroidTools.InstallFailedException: Unexpected install output:  pkg: /data/local/tmp/com.bergmannsoft.aprepara-Signed.apk
1>Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED]
1>
1>   em Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess(String output, String packageName) na E:\A\_work\1824\s\External\androidtools\Mono.AndroidTools\Internal\AdbOutputParsing.cs:linha 345
1>   em Mono.AndroidTools.AndroidDevice.<>c__DisplayClass95_0.<InstallPackage>b__0(Task`1 t) na E:\A\_work\1824\s\External\androidtools\Mono.AndroidTools\AndroidDevice.cs:linha 753
1>   em System.Threading.Tasks.ContinuationTaskFromResultTask`1.InnerInvoke()
1>   em System.Threading.Tasks.Task.Execute()
1>ADB0010: Unexpected install output:   pkg: /data/local/tmp/com.bergmannsoft.aprepara-Signed.apk
1>Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED]
1>
1>   em Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess(String output, String packageName) na E:\A\_work\1824\s\External\androidtools\Mono.AndroidTools\Internal\AdbOutputParsing.cs:linha 345
1>   em Mono.AndroidTools.AndroidDevice.<>c__DisplayClass95_0.<InstallPackage>b__0(Task`1 t) na E:\A\_work\1824\s\External\androidtools\Mono.AndroidTools\AndroidDevice.cs:linha 753
1>   em System.Threading.Tasks.ContinuationTaskFromResultTask`1.InnerInvoke()
1>   em System.Threading.Tasks.Task.Execute()
1>Projeto de compilação pronto "Ishpia.Droid.csproj" -- FALHA.
1>FALHA da compilação.
1>Deployment failed to nexus_5x_api_23.
========== Compilar: 0 com êxito, 0 com falha, 2 atualizados, 0 ignorados ==========
========== Implantação: 0 com êxito, 1 com falha, 0 ignorados ==========

Already cleaned, deleted folders "bin" and "obj" many times, cleared caches packages, nuget and always shows the error.

Could anyone help me understand why the error only happens in Android 6.0/6.1?

My manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="150" android:versionName="3.2" package="com.bergmannsoft.aprepara" android:installLocation="auto">
    <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="27" />
  <!-- Google Maps for Android v2 requires OpenGL ES v2 -->
  <uses-feature android:glEsVersion="0x00020000" android:required="true" />
  <!-- We need to be able to download map tiles and access Google Play Services-->
  <uses-permission android:name="android.permission.INTERNET" android:required="true" />
  <uses-permission android:name="android.permission.CAMERA" android:required="true" />
  <!-- Allow the application to access Google web-based services. -->
  <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
  <!-- Google Maps for Android v2 will cache map tiles on external storage -->
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:required="true" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:required="true" />
  <!-- Google Maps for Android v2 needs this permission so that it may check the connection state as it must download data -->
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" android:required="true" />
  <!-- These are optional, but recommended. They will allow Maps to use the My Location provider. -->
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:required="true" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:required="true" />
  <!-- Outras permissoes-->
  <uses-permission android:name="android.permission.CALL_PHONE" android:required="true" />
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" android:required="true" />
  <!-- Permission to receive remote notifications from Google Play Services -->
  <!-- Notice here that we have the package name of our application as a prefix on the permissions. -->
  <uses-permission android:name="com.bergmannsoft.aprepara.permission.MAPS_RECEIVE" android:required="true" />
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" android:required="true" />
  <uses-permission android:name="android.permission.READ_USER_DICTIONARY" android:required="true" />
  <!-- GCM-->
  <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
  <uses-permission android:name="android.permission.WAKE_LOCK" />
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
  <uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" />
  <uses-permission android:name="com.bergmannsoft.aprepara.permission.C2D_MESSAGE" />
  <permission android:name="com.bergmannsoft.aprepara.permission.C2D_MESSAGE" android:protectionLevel="signature" />
  <!-- BOOT -->
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  <!-- MAP-->
  <permission android:name="com.bergmannsoft.aprepara.permission.MAPS_RECEIVE" android:protectionLevel="signature" />
  <!-- Declaring Service in Manifest -->
  <service android:name="Ishpia.Droid.Activities.Services.Order.PostService" android:exported="false" />
  <service android:name="Ishpia.Droid.Activities.Services.Order.OrderService" android:exported="false" />
  <service android:name="Ishpia.Droid.Activities.Services.Periodic.PeriodicService" android:exported="false" />
  <!-- APLICATION -->
    <application android:allowBackup="true" android:label="@string/app_title" android:icon="@mipmap/icon" android:roundIcon="@mipmap/icon_round" android:largeHeap="true" android:supportsRtl="true" android:theme="@style/AppTheme.NoActionBarNotExtended">
    <!-- Put your Google Maps V2 API Key here. -->
    <meta-data android:name="com.google.android.geo.API_KEY" android:value="XXXXXXXXXXXXXXXXXXXXX" />
    <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
    <!-- FCM/GCM -->
    <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_stat_ic_notification" />
    <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/background" />
    <!-- [END fcm_default_icon] -->
    <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
    <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
      <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="${applicationId}" />
      </intent-filter>
    </receiver>
    <!-- BOOT DEVICE -->
    <receiver android:name="Ishpia.Droid.Activities.Services.Boot.BootReceiver" android:enabled="true" android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
      <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
    </receiver>
    <!-- FILE PROVIDER -->
    <provider android:name="android.support.v4.content.FileProvider" android:grantUriPermissions="true" android:exported="false" android:authorities="${applicationId}.fileprovider">
      <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_provider_paths" />
    </provider>
    </application>
</manifest>

Solution

  • Honestly, this problem was very confusing for me. However, Robert Bruce (@6157192) was right, the problem was in Manifest.xml, but not in the configuration Manifest.Xml, in the Manifest.Xml generated after the build.

    I'll describe the steps to finding the best "solution" for me:

    1. I ran Android Lint (@SushiHangover / @4984832) several times, making the required adjustments, reviewing and cleaning the main Manifest.xml.

    C:\Workspace\Android\sdk\tools\bin>lint.bat  C:\Workspace\htdocs\Projetos\aprepara-xamarin-raksha\Ishpia.Droid\
    

    2. Cleaned, recompiled and deployed with Visual Studio 2017 and Androi Emulator Nexus 5x (API 23).

    Obviously, the error occurred, however if you look at the output terminal, it is generated apk for installation.

    C:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.25\\bin\java.exe -jar "C:\Program Files (x86)\Android\android-sdk\build-tools\27.0.3\lib\apksigner.jar" sign --ks "C:\Users\Claudio\AppData\Local\Xamarin\Mono for Android\debug.keystore" --ks-pass pass:android --ks-key-alias androiddebugkey --key-pass pass:android --min-sdk-version 22 --max-sdk-version 27  C:\Workspace\htdocs\Projetos\aprepara-xamarin-raksha\Ishpia.Droid\bin\Debug\ **com.bergmannsoft.aprepara-Signed.apk**
    

    com.bergmannsoft.aprepara-Signed.apk

    3. Using the apkanalyzer in win, I exported the generated manifest.xml after compilation.

    apkanalyzer.cmd manifest print C:\Workspace\htdocs\Projetos\aprepara-xamarin-raksha\Ishpia.Droid\bin\Debug\com.bergmannsoft.aprepara-Signed.apk > android.xml
    

    Now the game was fun, because after several days reviewing and remaking Manifest.xml, I find that the error was in the Manifest.xml generated after the compilation, because depending on the implementation of its class, Xamarin (not sure if it's just the Xamarin ) will manipulate the XML and add other information.

    And the error was actually in Manifest.xml, but not what was editing, in generated after compilation.

    Boot Receiver permissions and classes were being generated twice.

    4. Now that I finally found where the error was, we went back to the tests .. tests .. tests .. many tests.

    TEST A (FAIL):

    Removing the classes of the attributes that were manipulating the Manifest.xml and generated error and putting all package names in the "Manifest" in lower case, the application was properly installed on Android 6.0 and the other versions (7.8 and 9).

    <!-- BOOT DEVICE -->
    <receiver android:name="ishpia.droid.activities.services.boot.bootreceiver" android:enabled="true" android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
      <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
    </receiver>
    
    <!-- SERVICE -->
    <service android:name="ishpia.droid.activities.services.order.postdervice" android:exported="false" />
    <service android:name="ishpia.droid.activities.services.order.orderservice" android:exported="false" />
    <service android:name="ishpia.droid.activities.services.periodic.periodicservice" android:exported="false" />
    

    But it generated a new problem, because in some real devices (not at all, in just a few models), the error was occurring:

    
    Fatal Exception: java.lang.RuntimeException: Unable to instantiate receiver ishpia.droid.activities.services.boot.bootreceiver: java.lang.ClassNotFoundException: Didn't find class "ishpia.droid.activities.services.boot.bootreceiver" on path: DexPathList[[zip file "/data/app/com.bergmannsoft.aprepara-x12fO8j-m_szPmi4Kc9Kyg==/base.apk"],nativeLibraryDirectories=[/data/app/com.bergmannsoft.aprepara-x12fO8j-m_szPmi4Kc9Kyg==/lib/arm, /data/app/com.bergmannsoft.aprepara-x12fO8j-m_szPmi4Kc9Kyg==/base.apk!/lib/armeabi-v7a, /system/lib, /system/vendor/lib]]
           at android.app.ActivityThread.handleReceiver(ActivityThread.java:3374)
           at android.app.ActivityThread.-wrap18(Unknown Source)
           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1807)
           at android.os.Handler.dispatchMessage(Handler.java:106)
           at android.os.Looper.loop(Looper.java:164)
           at android.app.ActivityThread.main(ActivityThread.java:7000)
           at java.lang.reflect.Method.invoke(Method.java)
           at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:441)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
    

    Apparently some devices did not find the BootReceiver class.

    TEST B (FAIL):

    Placing the names in capitlize of the classes in Manifest.xml, worked in versions (7,8 and 9) except the Android version 6. Actually, not being able to understand why the error only occurs in version 6.

    <!-- BOOT DEVICE -->
    <receiver android:name="Ishpia.Droid.Activities.Services.Boot.Bootreceiver" android:enabled="true" android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
    ..
    </receiver>
    

    TEST N (OK at moment):

    This was the best solution I found for my application.

    Remove all services and receiver from Manifest.xml, thus:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
              xmlns:tools="http://schemas.android.com/tools"
              tools:ignore="GoogleAppIndexingWarning"
              android:versionCode="152" 
              android:versionName="3.2" 
              package="com.bergmannsoft.aprepara" 
              android:installLocation="auto">
        <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="27" />
      <!-- Google Maps for Android v2 requires OpenGL ES v2 -->
      <uses-feature android:glEsVersion="0x00020000" android:required="true" />
      <!-- USER PERMISSION-->
      <uses-permission android:name="android.permission.INTERNET" android:required="true" />
      <uses-permission android:name="android.permission.CAMERA" android:required="true" />
      <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:required="true" />
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:required="true" />
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" android:required="true" />
      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:required="true" />
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:required="true" />
      <uses-permission android:name="android.permission.CALL_PHONE" android:required="true" />
      <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" android:required="true" />
      <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" android:required="true" />
      <uses-permission android:name="android.permission.READ_USER_DICTIONARY" android:required="true" />
      <uses-permission android:name="android.permission.WAKE_LOCK" />
      <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
      <uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" />
      <!-- PERMISSION-->
      <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
      <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
      <uses-permission android:name="com.bergmannsoft.aprepara.permission.MAPS_RECEIVE" android:required="true" />  
      <uses-permission android:name="com.bergmannsoft.aprepara.permission.C2D_MESSAGE" />
      <permission android:name="com.bergmannsoft.aprepara.permission.MAPS_RECEIVE" android:protectionLevel="signature" />
      <permission android:name="com.bergmannsoft.aprepara.permission.C2D_MESSAGE" android:protectionLevel="signature" />
      <!-- APLICATION -->
        <application android:allowBackup="false" android:label="@string/app_title" android:icon="@mipmap/icon" android:roundIcon="@mipmap/icon_round" android:largeHeap="true" android:supportsRtl="true" android:theme="@style/AppTheme.NoActionBarNotExtended">
        <!-- Put your Google Maps V2 API Key here. -->
        <meta-data android:name="com.google.android.geo.API_KEY" android:value="XXXXXXXXXXXXXXX" />
        <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
        <!-- FCM/GCM -->
        <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_stat_ic_notification" />
        <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/background" />
        <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
        <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
          <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name="${applicationId}" />
          </intent-filter>
        </receiver>
        <!-- FILE PROVIDER -->
        <provider android:name="android.support.v4.content.FileProvider" android:grantUriPermissions="true" android:exported="false" android:authorities="${applicationId}.fileprovider">
          <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_provider_paths" />
        </provider>
      </application>
    </manifest>
    

    And insert as attributes directly into Xamarin classes (after xamarin will insert into Manifest during compilation).

    BroadcastReceiver

    namespace Ishpia.Droid.Activities.Services.Boot
    {
        [BroadcastReceiver(Enabled = true, Exported = false, Permission = "android.permission.RECEIVE_BOOT_COMPLETED")]
        [IntentFilter(new[] { Intent.ActionBootCompleted }, Priority = (int)IntentFilterPriority.LowPriority, Categories = new[] { Intent.CategoryDefault })]
        public class BootReceiver : BroadcastReceiver
        {
            public override void OnReceive(Context context, Intent intent)
            {
                Intent i = new Intent(context, typeof(SplashActivity));
                i.AddFlags(ActivityFlags.NewTask);
                context.StartActivity(i);
            }
        }
    }
    

    OrderService

    namespace Ishpia.Droid.Activities.Services.Order
    {
        [Service (Exported = false)]
        public class OrderService : IntentService
        {
            ...
        }
    }
    

    PostService

    namespace Ishpia.Droid.Activities.Services.Order
    {
        [Service(Exported = false)]
        class PostService : IntentService
        {
        ..
        }
    }
    

    PeriodicService

    namespace Ishpia.Droid.Activities.Services.Periodic
    {
        [Service(Exported = false)]
        class PeriodicService : Service
        {
        ...
        }
    }
    

    Xamarin will export Manifest.xml after compiling:

            <service
                android:name="md556d51780b7ddda82c5xxxxxxxxxxxxx.RegistrationIntentService"
                android:exported="false" />
    
            <service
                android:name="md527cd63edec29ae2b7xxxxxxxxxxxxx.PeriodicService"
                android:exported="false" />
    
            <service
                android:name="md51a4cc6308c061c7f0xxxxxxxxxxxxx.OrderService"
                android:exported="false" />
    
            <service
                android:name="md51a4cc6308c061c7fxxxxxxxxxxxxx.PostService"
                android:exported="false" />
    
            <receiver
                android:name="md53c9e18cf96d129xxxxxxxxxxxxx.BootReceiver"
                android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
                android:enabled="true"
                android:exported="false">
    
                <intent-filter
                    android:priority="-1000">
    
                    <action
                        android:name="android.intent.action.BOOT_COMPLETED" />
    
                    <category
                        android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </receiver>
    

    These were the steps taken in my application to solve the problem that was occurring, I think that is not a simple problem to solve. I may have lacked experience with Xamarin, but I'm putting my solution in case I can help other people.