AppConnect wrapping considerations

SQLCipher considerations

SQLCipher library version

The Secure Apps Manager, the Secure Apps Manager for AppStation, and the AppConnect wrapper in wrapped apps all use SQLCipher 4.0.1, which is a 64-bit library.

Using both SQLCipher and SQLLite is not supported

Using SQLCipher and Android SQLite databases at the same time is not supported. Developers should move all databases to either SQLCipher or Android SQLite.

Encryption of the SQLCipher database

If your app uses SQLCipher calls to encrypt data, the wrapping process makes changes so that the Secure Apps Manager or Secure Apps Manager for AppStation manages the encryption key for the SQL data. Therefore, the wrapping process encrypts the SQLCipher database a second time, because it is already encrypted by SQLCipher. This second layer of encryption can have performance impact on your app.

To avoid the performance impact, you can use the wrapping flag -ignoreSqlcipher with Generation 2 wrapped apps. Use this flag only for new installations, not upgrades, of your app where the app is wrapped with wrapper version 8.2.1 or supported newer versions. Do not use the flag if your wrapped app was previously installed on devices. If you do, your database will not be accessible.

When you use the -ignoreSqlcipher flag, continue to use it every time you wrap the app.

You can use the -ignoreSqlcipher flag for wrapping an app that uses the Room Persistence Library.

DownloadManager API considerations

If your app uses the Android DownloadManager API, the secure FileManager that Ivanti provides must also be installed on the device. The FileManager ensures downloaded files remain in the secure container. Only secure apps can access the downloaded files.

Inform the server administrator that your app requires the FileManager.

Google Cloud Messaging considerations

Secure Apps for Android supports Google Cloud Messaging for Android (GCM) in wrapped apps. GCM allows you to send data from an app server to these apps.

Secure Apps supports using GCM for sending HTTP messages from an app server to wrapped apps (HTTP downstream messages). The feature requires that the app uses the GoogleCloudMessaging class. The deprecated class GCMRegistrar is not supported.

Unsupported GCM features

Secure Apps does not support these GCM features:

  • XMPP
  • upstream messaging

Situations when GCM messages are discarded

In the following situations, the app does not receive GCM messages, and the messages are discarded:

  • The device user is logged out of secure apps after a device restart or Secure Apps Manager (or Secure Apps Manager for AppStation) termination.
  • In this situation, the user has a notification that says “Logged out. No app activity. Tap to log in.”
  • The app is unauthorized (blocked) on the device.

Firebase Cloud Messaging and Crashlytics support

A wrapped app can use Firebase Cloud Messaging (FCM) the same as any Android app. To support FCM in a wrapped app, on the Firebase web console, you create a Firebase project that specifies your unwrapped app. The unwrapped app and the wrapped app can each then receive the FCM messages. If both the wrapped app and the unwrapped app are on the same device, they both receive the FCM messages. Unauthorized wrapped apps do not receive the FCM messages.

Generation 1 wrapping does not support the Firebase Cloud Messaging library starting with com.google.firebase.firebase-messaging.17.0.0.

If the -enableCrashlytics or -allowCrashlytics option is used when wrapping the app, the crash data is available on the Firebase Crashlytics console. The app must support Firebase Crashlytics. The crash reports appear for the unwrapped app package name on the console. However, the reports include the label (wrapped app), which identifies the report as an AppConnect wrapped app crash report.

The -googleService options can be used with the wrap tool to allow the replacement of Firebase authentication data with one that is related to the wrapped package's named project. For example, if the original package name for the app was com.company.name, the wrapped package name is prefixed by forgepond., giving you forgepond.com.company.name.

MediaPlayer and MediaMetaDataRetriever Internet permission requirement

You can wrap apps that use the android.media.MediaPlayer and android.media.MediaMetaDataRetriever APIs. However, wrapper support of these APIs require that wrapped apps set the Android Internet permission.

You can set the Android Internet permission in your app in one of the following ways:

  • Add the permission android.permission.INTERNET to your app’s AndroidManifest.xml file before you submit it to the AppConnect Wrapping Portal.
  • In the AppConnect Wrapping Portal, add the following flag in the Advanced Option section in the Extra options field:

    -addInternetPermission

Ivanti provides a sample app, ApiUsageDemo, that demonstrates the necessary code.

Image selection from outside the AppConnect container

To select an image from outside the AppConnect container, such as the device’s gallery, the app must be granted the permission Manifest.permission.READ_EXTERNAL_STORAGE. This permission is necessary because of how the wrapper implements selecting an image from outside the AppConnect container.

Do the following in your app if it selects images from outside the AppConnect container:

  1. Add the permission android.permission.READ_EXTERNAL_STORAGE to your app’s AndroidManifest.xml file before you submit it to the AppConnect Wrapping Portal.
  2. Provide code to grant the permission at runtime.

Ivanti provides a sample app, ApiUsageDemo, that demonstrates the necessary code.

External storage permissions

When a wrapped app saves data to its own app-specific directory on external storage, such as an SD card, the wrapper saves the data to a particular location depending on the wrapper version. The storage location, which is returned by getExternalFilesDir(), determines whether the wrapped app requires the external storage permission (WRITE_EXTERNAL_STORAGE). The following table provides the storage location and permission requirements.

Table 10.  External storage permissions

Wrapper version

External storage location

Does the wrapped app require the WRITE_EXTERNAL_STORAGE

permission?

Prior to 8.2

/<sdcard_path>/AppConnect/

Yes.

The permission is necessary because the storage location is not specific to the wrapped app’s package name.

8.2 or supported newer versions

/<sdcard_path>/Android/data/<wrapped_pkg>/

No.

The permission is not necessary because the storage location is specific to the wrapped app’s package name.

However, consider the case when you are re-wrapping an app that was previously wrapped with a wrapper version prior to 8.2. In this case, the wrapped app still requires the WRITE_EXTERNAL_STORAGE permission. The wrapped app still needs the permission so that the wrapper can move the data from the pre-8.2 storage location to the new location. The wrapper moves the data after the wrapped app finishes its initialization, so make sure the permission is granted during initialization. After the wrapper has moved the data, later versions of the wrapped app do not require the WRITE_EXTERNAL_STORAGE permission to save data to the app-specific external storage directory.

Apps request permissions at runtime when running on Android 6.0 or supported newer versions. When running Android versions prior 6.0, apps request permissions at installation time. Therefore, the runtime permission requirements for moving the data do not apply on Android versions prior to 6.0.

Support for scoped storage

AppConnect supports scoped storage. If the targetSdkVersion of the app is set to 30, ensure that the app is wrapped with the Generation 2 Wrapper. No additional setup is required.

IMPORTANT: If you set targetSdkVersion to 29, you can wrap the app with the Generation 1 wrapper. However, ensure that android:requestLegacyExternalStorage="true" in AndroidManifest.xml. Otherwise, Android activates the ScopedStorage by default.

Receiving information from outside the AppConnect container

Sometimes wrapped apps need to receive information from outside the AppConnect container that is different than what is supported by the server policies and configurations. For example, an app might need to receive a system broadcast event.

If your wrapped app has this requirement, you can add a wrapping flag that specifies which Android intent action you want to allow the app to receive. The wrapping flag is -allowIntentAction. The flag is followed by a list of actions to allow. Separate actions with spaces.

For example:

-allowIntentAction android.intent.action.TIMEZONE_CHANGED

USB OTG support

Wrapped apps can create, read, and write unencrypted image and text files to a USB OTG (on-the-go) drive that uses a FAT32 file system.

For a wrapped app to be able to take these actions, a key-value pair is required on the Secure Apps Manager’s AppConnect app configuration on Core. The new key is MI_AC_ENABLE_USB_UNENCRYPTED_ACCESS. Access to files on a USB OTG drive is allowed only if the value of the key is true. The value defaults to false.

This feature is supported only with Core and Connected Cloud. It is not supported with Ivanti Neurons for MDM.

Preference API usage

If your app uses the PreferenceActivity or PreferenceFragment APIs:

  • If you wrap with the Generation 1 wrapper, change your app to use the PreferenceFragmentCompat APIs for the app to behave correctly on Android 9.0 or supported newer versions.
  • If you wrap with the Generation 2 wrapper, Ivanti recommends that you change your app to use the PreferenceFragmentCompat APIs, because Google has deprecated the PreferenceActivity and PreferenceFragment APIs.

Google deprecated the PreferenceActivity API in Android 3.0 and the PreferenceFragment API in Android 9.0 (API level 28).

64-bit support

  • Generation 1 wrapper provides 64-bit support by default.
  • Generation 2 wrapper wraps apps with native libraries in both 32-bit and 64-bit versions.
    However, if the app does not use native libraries, the app is wrapped only with 64-bit support.

You can disable 64-bit mode by entering the -disableArm64 option. For more information about using the option see Uploading and wrapping an app and Preparing to use the wrapping tool.

Linking native Java methods

In wrapped apps, native java methods are linked as soon as the client native library loads. In unwrapped apps, the methods are linked on their first call.

Configure the flag -keepJavaNativesLazyLinking to preserve the old linking mechanism for backward compatibility. However, do not use this option for wrapping Xamarin apps.

You can disable 64-bit mode by entering the -disableArm64 option. For more information about using the option see Uploading and wrapping an app and Preparing to use the wrapping tool.