App Development and Execution (Android - Android Studio)

Establish App Development Environment

You can develop a Nexacro-based Android app by using Android Studio, the official app development tool of Android. Otherwise, you can use App Builder, which is one of Nexacro products. This chapter explains how to develop an app by using Android Studio. The process of developing a Nexacro-based Android app is basically the same as that of a usual Android app.

If you have established the app development environment already, you can skip this section, Establish App Development Environment.

The installation file of Android Studio includes a software development kit (SDK). Click on the below link to download the installation file appropriate for your running environment.

https://developer.android.com/studio/index.html

This chapter is written based on the 2023.3.1 version of Android Studio.

Develop App Project

Once the app development environment is established, open Android Studio to get ready to develop an app running in Android. Before entering an app project, you should find the archive files that you built in Nexacro Studio and locate them in the designated directory.

Create a project

1

Unless you have already opened a project , create a new project in the Welcome to Android Studio window. Click Create New Project as seen in the below picture.

android_studio_3.0_open_project

If you want to create a new project with a project already opened, navigate to the below menu.

File > New > New Project

2

Choose a project template provided by Android.

Selection of templates affects an app structure, screen layout as well as the composition of files. Since it is enough for us to have a basic project that just can contain a Nexacro-based app, select Empty Views Activity and click Next.

android_studio_add_an_activity_empty

3

Configure some settings including the app name, package name and project location.

android_studio_create_project



Description

1

Name

Specify the name of your app.

2

Package Name

Specify the package name.

3

Save location

Specify the location where you want to locally store your project.

4

Language

Select the development language. Although the default language is Kotlin, Java is used in this chapter's sample.

5

Minimum API

Set the minimum level of an SDK. Whenever you change the SDK level, the information appears below about the device compatibility with the relevant API level.

The minimum level of Android that Nexacro supports is 5.0. Accordingly, you should choose an SDK that supports the API level 21 or higher.

4

As soon as you click the Finish button, the project is created.

As the project window is opened, additional necessary files are downloaded and installed automatically.

Set Nexacro libraries

Set the Nexacro Android Archive (AAR) file provided for use in app development in the Android project. No setting is required. Just copy it to the designated path.

Library File

Path

Requiered

NexacroLib-release.aar

[Project path]\app\libs\

Required

Acceleration-release.aar

AudioPlayer-release.aar

AudioRecorder-release.aar

BluetoothLE-release.aar

Camera-release.aar

Contact-release.aar

ExternalAPI-release.aar

Geolocation-release.aar

ImagePicker-release.aar

LiteDB-release.aar

Network-release.aar

Phone-release.aar

Sms-release.aar

Vibrate-release.aar

XPush-release.aar

[Project path]]\app\libs\

Added selectively depending on the Device API used by the app

If you want to copy the library files to each designated location in your actual project, you should select the Project view option from the dropdown at the top of the Project window. When you install Android Studio, the view mode is set to Android by default. You should change the view mode to Project to see the actual file structure of a project.

android_studio_project_explorer

1

Copy the Nexacroib-release.aar file and the required aar files to the [Project path > app > libs] folder.

archive_library_설정

2

Select "Dependencies" from the menu [File > Project Structure], select "app" from the Modules item, click the "+" button, and select the "JAR/AAR Dependencyy" item.

3

Enter the aar file path in the input window and click the [OK] button.

4

Confirm that the aar file is added to the app > build.gradle.kts file.

For dependency management information, see Dependency Management.

Set resources

In this stage, you can set launch images, icons, messages and layouts applied to your app. The Android system can offer optimal settings for screens if you make a list of resources according to device screen sizes and screen densities and then allocate each of them to appropriate folders.

Basic resources are included in the Nexacro Android Archive (AAR) file. If the default resources are used, no specific setup is required.

See the official Android user guide for further details on resources.

https://developer.android.com/guide/topics/resources/providing-resources

Set images

Images used in an app should be placed in each appropriate directory under the res directory according to screen densities. For example, images for a splash screen should be located in drawable folders while app icon images are placed in mipmap folders. Image files should be put in different folders according to the resolution levels that are supported by the relevant app.

Images

Description

ic_launcher.png

This is the image of an app icon that appears on the home screen.

You can change the name of the image file in the AndroidManifest.xml file.

splashimage_phone_landscape.png

This is the image of a splash screen in landscape orientation, applied to an Android phone. (The name must be written in lower case.)

splashimage_phone_portrait.png

This is the image of a splash screen in portrait orientation, applied to an Android phone. (The name must be written in lower case.)

splashimage_pad_landscape.png

This is the image of a splash screen in landscape orientation, applied to an Android tablet. (The name must be written in lower case.)

splashimage_pad_portrait.png

This is the image of a splash screen in portrait orientation, applied to an Android tablet. (The name must be written in lower case.)

Even if you do not set images separately for the launcher icon and splash screen, your app will operate nevertheless because the default settings will be applied instead.

Set strings

The default string settings are applied according to the strings.xml file settings included in the Nexacro Android Archive (AAR) file. To change the default string settings, you can create a strings.xml file in the values, values-ko, values-ja, values-zh folders under the res folder and set only the items you want to change.

The code below is the strings.xml file included in the Nexacro Android archive file. The contents may vary depending on the distributed version

$r_title(values\strings.xml)
<?xml version="1.0" encoding="utf-8"?>

<resources>
 <string name="needupdate">It is need to update. \nIt will start after the update is completed.</string>
 <string name="update">Update</string>
 <string name="exit">Exit</string>
 <string name="updateFail">Update is fail. \nPlease restart.</string>
 <string name="loadingFail">First loading is fail. \nPlease restart.</string>
 <string name="updatedone">Update is Completed.</string>
 <string name="checkforupdates">Check for updates.</string>
 <string name="installforupdates">Install for updates.</string>
 <string name="ok">OK</string>
 <string name="downloadingforupdates">Downloading for updates.</string>
 <string name="allow_permission">Allow the permission as the permission is required for the normal function of the engine update.</string>
 <string name="denied_permission">It ends with denial of engine update permission.</string>
 <string name="cancel">Cancel</string>
 <string name="ssl_invalid">The SSL certificate is invalid. Continue?</string>
</resources>

While you can change those strings to suit your situation, you should not change their name attributes because they are predefined for the app.

If you want to add strings written in a non-English language like Korean or Japanese, add a folder under the res directory with a name like values-ko or values-ja. Then, add the strings.xml file to the created folder. See the official Android user guide for further details.

https://developer.android.com/training/basics/supporting-devices/languages.html

Set Config

Basic config settings are applied according to the settings of the nexacro_config.xml file included in the Nexacro Android Archive (AAR) file. To change the config settings, create and set the nexacro_config.xml file in the xml folder.

The code below is the content of the nexacro_config.xml file included in the Nexacro Android archive file. The contents may vary depending on the distributed version

$r_title(xml\nexacro_config.xml)

<?xml version="1.0" encoding="UTF-8"?>
<nexacro-config>
    <application style="default" dialog-position="bottom" file-logging="true" quiet="false" loglevel="debug" tracemode="none" traceduration="-1"/>
    <notification enable="true" handler="com.nexacro.notification.DefaultHandler"/>
    <xpush-server request-missing-message="false" sender-id="1234567890"/>
    <updator cancelable="true" force="true" restart="false" errormsg="true" quiet="false" failpass="true"/>
    <log filepath="%SD_CARD%nreLog.log" filesize="408960" backupfilecount="5"/>
</nexacro-config>

The below table shows the features that you can set in nexacro_config.xml.

Features

Property

Value

Description

application

dialog-position

"top" | "center" | "bottom"

This property sets the position of a pop-up for showing the progress of app updating.

file-logging

"true" | "false"

This property determines whether to log loading errors in the form of a file.

If "true", your app will attempt to save a log file first to the external storage (context.getExternalCacheDir()). If the external storage is unavailable, the internal storage is the next destination (context.getCacheDir()).

The directory and file name for saving a log file is as follows: [external/internal storage]/logs/yyyy_MM_dd.txt.

quiet

"true" | "false"

This property determines whether to display a pop-up that indicates app launching.

If "true", the message "Loading Application" will not be printed.

updator

force

"true" | "false"

This property determines whether to display a pop-up for announcing the existence of an update, contained in start_android.json.

cancelable

"true" | "false"

If "true", updating will be conducted automatically without pop-up announcement.

errormsg

"true" | "false"

This property determines whether to display a pop-up for showing the error information when the loading of the app fails.

quiet

"true" | "false"

This property determines whether to display a pop-up that asks you whether to update the app.

Even if you specify "true", the progress of app updating will be displayed when there is an update file.

failpass

"true" | "false"

Set whether to ignore the update errors or not

xpush-server

request-missing-message

"true" | "false"

This property determines whether to automatically request messages that you have not received from an XPush server.

notification

enable

"true" | "false"

This property determines whether to use the notification feature.

handler

“[function name]”

This property sets a function to process the message or data of a notification.

The default value is “com.nexacro.notification.DefaultHandler”.

Click on the below links for the details on the storage path defined by the file-logging property.


https://developer.android.com/reference/android/content/Context.html#getExternalCacheDir()

https://developer.android.com/reference/android/content/Context.html#getCacheDir()

Set build environment

You should modify MainActivity.java and AndroidManifest.xml —default files created in the process of creating an Android project—in a way that suits Nexacro.

MainActivity.java

If you do not specify another name for a main activity at the creation of a project, the activity will be created with the name MainActivity.java. To find the file MainActivity.java, navigate to the folder of the relevant package name under the directory [project > app > src > main > java]. Then, modify the file as below.

$r_title(MainActivity.java)
package com.example.hellonexacroandroid;

import android.os.Bundle;
import com.nexacro.NexacroActivity;

public class MainActivity extends NexacroActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

		// Update Type: Server, Update
        setProjectURL("http://[URL]/");
        setBootstrapURL("http://[URL]/start_android.json");

		// Update Type: Local
		// setBootstrapURL("file:///android_asset/archive/start_android.json");
    }
}

plugin_config.xml

The plugin_config.xml file is located in [Project > app > src > main > res > xml]. It contains basic information about the Device API and necessary information. Refer to the code below to write the required information.

If you did not set any other libraries aside from Nexacroib-release.aar when setting up Nexacro libraries, the operations will not be affected, even in the absence of the plugin_config.xml file.

$r_title(plugin_config.xml)


<?xml version="1.0" encoding="UTF-8"?>
<plugin-config>
    <!-- Nexacro Device API -->
    <plugin name="Network" class="com.nexacro.deviceapi.Network" onload="false"/>
    <plugin name="Geolocation" class="com.nexacro.deviceapi.Geolocation" onload="false"/>
    <plugin name="Acceleration" class="com.nexacro.deviceapi.Acceleration" onload="false"/>
    <plugin name="Sound" class="com.nexacro.deviceapi.AudioPlayer" onload="false"/>
    <plugin name="AudioRecorder" class="com.nexacro.deviceapi.AudioRecorder" onload="false"/>
    <plugin name="Camera" class="com.nexacro.deviceapi.Camera" onload="false"/>
    <plugin name="ImagePicker" class="com.nexacro.deviceapi.ImagePicker" onload="false"/>
    <plugin name="ExternalAPI" class="com.nexacro.deviceapi.ExternalAPI" onload="false"/>
    <plugin name="Vibrator" class="com.nexacro.deviceapi.Vibrate" onload="false"/>
    <plugin name="Call" class="com.nexacro.deviceapi.Phone" onload="false"/>
    <plugin name="Sms" class="com.nexacro.deviceapi.SmsManager" onload="false"/>
    <plugin name="ContactSet" class="com.nexacro.deviceapi.Contact" onload="false"/>
    <plugin name="SQLStatement" class="com.nexacro.deviceapi.LiteDBStatement" onload="false"/>
    <plugin name="SQLConnection" class="com.nexacro.deviceapi.LiteDBConnection" onload="false"/>
</plugin-config>

AndroidManifest.xml

The AndroidManifest.xml file, which is located in the directory [project > app > src > main], contains basic information about your app and necessary information for performing specific functionalities. Modify the file as shown in the below sample.

$r_title(AndroidManifest.xml)


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.HelloNexacroAndroid"
        android:usesCleartextTraffic="true"
        tools:targetApi="31">

        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="OPEN_NEXACRO_ACTIVITY_EXAMPLE" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

If your app targets the SDK version 28 or higher, you must set the usesCleartextTraffic attribute to "true" to maintain HTTP traffic.

If you do not set the attribute, HTTP traffic will not be allowed because the attribute defaults to "false".

https://developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic


<application

android:allowBackup="true"

android:usesCleartextTraffic="true"

AndroidManifest.xml > Additional privilege settings

Set necessary permissions and other information according to the features that your app is equipped with. For example, add the below sample to the manifest file if you want your app to provide the camera feature.

...
<uses-permission android:name="android.permission.CAMERA" />
<activity android:name="com.nexacro.deviceAPI.CameraListener"
	android:screenOrientation="landscape">
	<intent-filter>
   		<category android:name="android.intent.category.LAUNCHER" />
	</intent-filter>
</activity>
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus"
	android:required="false"/>
...

The below list contains sets of code to set the permissions for frequently-used features. Pick items necessary for your app and add them to AndroidManifest.xml. If you want to see all the permissions defined in Android, go to Manifest.permission.

If you execute your app without setting the permissions necessary for certain features of your app, relevant features will not function with a message that you do not have a permission for the feature.

<!-- AudioPlayer, AudioRecorder -->
<uses-permission android:name="android.permission.RECORD_AUDIO" /> 
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<!-- Call -->
<uses-permission android:name="android.permission.CALL_PHONE" />
<!-- Contact -->
<uses-permission android:name="android.permission.READ_CONTACTS" /> 
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<!-- Camera -->
<uses-permission android:name="android.permission.CAMERA" /> 
<activity android:name="com.nexacro.deviceAPI.CameraListener" android:screenOrientation="landscape">
	<intent-filter>
    	<category android:name="android.intent.category.LAUNCHER" />
	</intent-filter>
</activity>
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<!-- Geolocation -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<!-- Acceleration -->
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" tools:ignore="HighSamplingRate" />
<!-- Map -->
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-library android:name="com.google.android.maps" /> 
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="user value" />

If you want to use Google Maps, you need to get an API key and insert it to the relevant configuration file. Click on the below link to see the details about it.

https://developers.google.com/maps/documentation/android/start#obtain_a_google_maps_api_key

<!-- SMS -->
<uses-permission android:name="android.permission.SEND_SMS" /> 
<uses-permission android:name="android.permission.RECEIVE_SMS" /> 
<uses-permission android:name="android.permission.READ_SMS" /> 
<uses-permission android:name="android.permission.WRITE_SMS" />

<receiver android:name="com.nexacro.deviceAPI.SmsRecv">
	<intent-filter>
		<action android:name="android.provider.Telephony.SMS_RECEIVED" />
	</intent-filter>
	<intent-filter>
		<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
		<data android:mimeType="application/vnd.wap.mms-message" />
	</intent-filter>
</receiver>
<!-- Vibrator -->
<uses-permission android:name="android.permission.VIBRATE" />
<!-- Bluetooth -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<service
	android:name="com.nexacro.deviceAPI.BluetoothLEAdapterService"
	android:enabled="true"
	android:exported="true">
</service>
<!-- ExternalAPI -->
<uses-permission android:name="android.permission.GET_TASKS" />
<!-- Etc -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

AndroidManifest.xml > FCM settings

About FCM messages

https://firebase.google.com/docs/cloud-messaging/concept-options

<!-- Adding NexacroNotificationService -->
<service android:name="com.nexacro.notification.NexacroNotificationService">
	<intent-filter>
		<action android:name="com.google.firebase.MESSAGING_EVENT" />
	</intent-filter>
</service>

<!-- Adding NexacroActivity intent-filter -->
<activity android:name="com.nexacro.NexacroActivity"
	android:launchMode="singleTask"
	android:noHistory="false"
	android:hardwareAccelerated="true"
	android:windowSoftInputMode="adjustResize"
	android:configChanges="orientation|keyboard|keyboardHidden|screenSize|navigation|uiMode">
	<intent-filter>
		<action android:name="OPEN_NEXACRO_ACTIVITY_EXAMPLE" />
		<category android:name="android.intent.category.DEFAULT" />
	</intent-filter>
</activity>

If you use FCM, the below code listings should be added to the build.gradle file. Basically, this configuration is automatically performed in Android Studio. If not performed automatically, however, you need to add the below code listings by yourself and download the google-services.json file, which is created in the Firebase console. Then, copy the JSON file to the module directory of your app.

Add Firebase to your Android project

https://firebase.google.com/docs/android/setup

AndroidManifest.xml > ImagePicker, Camera, FileUpload, FileDailog settings

If you set targetsdk version to 24 or higher and use ImagePicker, FileDialog, FileUpload, and Camera components (Camera component with the targetsdk version 29 or higher), you need to create the file_paths.xml file in res/xml folder, add the following items to AndroidManifest.xml file and build.gradle file.

When using the capture property of the input tag in the HTML content connected to the WebBrowser component, an identical setting is required to access the file.

$r_title(file_paths.xml)
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-cache-path name="cache" path="."/>
    <external-files-path name="files" path="./"/>
</paths>
$r_title(AndroidManifest.xml / FileProvider)
<provider
	android:name="android.support.v4.content.FileProvider"
	android:authorities="${applicationId}.fileprovider"
	android:exported="false"
	android:grantUriPermissions="true">
	<meta-data
		android:name="android.support.FILE_PROVIDER_PATHS"
		android:resource="@xml/file_paths"/>
</provider>

<!-- AndroidX -->
<provider
	android:name="androidx.core.content.FileProvider"
	android:authorities="${applicationId}.fileprovider"
	android:exported="false"
	android:grantUriPermissions="true">
	<meta-data
		android:name="android.support.FILE_PROVIDER_PATHS"
		android:resource="@xml/file_paths"/>
</provider>
$r_title(build.gradle / exifinterface)

dependencies {
    implementation 'com.android.support:exifinterface:28.0.0'
	//AndroidX
	implementation 'androidx.exifinterface:exifinterface:1.3.2'
}

Dependency Management

Write the library information in the build.gradle file.

implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation "androidx.room:room-runtime:2.4.3"
implementation 'androidx.exifinterface:exifinterface:1.3.4'
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
annotationProcessor "androidx.room:room-compiler:2.4.3"

When using XPush, add the library information below.

implementation 'org.slf4j:slf4j-api:1.7.36'

When using Firebase, add the library information below.

implementation 'com.google.firebase:firebase-core:21.1.1'
implementation 'com.google.firebase:firebase-messaging:23.0.8'

Set your app stand-alone in disconnected environments

You can run your app without a network connection if you set the update type to "Local" or "Update (Local+Server)" when packing the app in Nexacro Studio. Normally, the Local type is appropriate for users who do not need a network connection while the Update (Local+Server) type suits users who usually maintain communications with servers but still need to operate apps even when networking is in trouble. To make your app stand-alone, you should prepare files necessary for execution and load them onto the app in the building process.

The files necessary for executing an app include modules, sources, resources and start_android.json, which are all obtained through the Packing (Archive&Update) process of Nexacro Studio. If you load those files onto the "archive" folder under the "assets" directory in your Android project before building an app, you can run the app without a network connection.

1

Create the "assets" folder in your project in Android Studio.

The "assets" directory is a logical storage used in an Android app. After creating the assets folder in your Android project, prepare files to use in the app, copy those files to the assets folder and build the APK of your app. By doing so, you can use those files when you launch the app. Since the assets folder is read-only, the files in this directory should not change during the execution of the app.

Right-click on app, the root folder of your project, and select [New > Folder > Assets Folder] from the context menu. Create the assets folder under the directory [project > app > src > main].

create_assets_1

2

Create the "archive" folder under the assets directory.

Right-click the assets folder under the directory [project > app > src > main] and select [New > Directory] from the context menu to create the "archive" folder under the assets folder.

3

Copy module, source and resource files to the assets/archive directory.

Copy module, source and resource files to the [project > app > src > main > assets > archive] directory. You can copy and paste files directly from File Explorer into Android Studio.

copy_archive_files

4

Check whether the folders and files have been added to the project successfully.

Go to the project view in Android Studio and check whether the added assets/archive folder and files under the folder are there.

asset_경로

Build

App test

You can test your app by connecting an Android device to your PC using a USB cable. In that case, you need to toggle the USB debugging option in the Developer Options menu in the device and to install a driver for the device.

Click on the below link to learn how to select the USB debugging option.

https://developer.android.com/studio/debug/dev-options

Select a virtual device or connected device from the device list at the top of Android Studio and execute Run.

You can see the log messages for executing the app through the Logcat window, which is situated at the bottom of the Android Studio screen.

logcat

Create installation file

To distribute your app that has been built completely, you should create a keystore that can identify your app and then should create a signed AAB, APK file. You need to create a keystore file just once at the beginning. When the app is updated, you can use the keystore file that you created already.

Click on the below link to go to the official Android user guide where you can learn how to create a keystore and signed APK.

http://developer.android.com/guide/publishing/app-signing.html

Select the menu [Build > Generate Singed Bundle/APK].

generate_signed_apk_menu

The default setting is to generate AAB files. If needed, you can select an APK item and generate an APK file.