OZ e-Form Developer
  • OZ e-Form Concepts
  • 🌈e-Form DEVELOPER
    • Day 1: Welcome On Board
      • About Course
      • Preparations
      • OZ e-Form Overview
    • Day 2: e-Form Design
      • Designer Environments
      • e-Form Layout Structure
      • e-Form Components
      • e-Form From Documents
      • Preview / Export / Save
      • Hands-on Practice
    • Day 3: Dynamic e-Form
      • e-Form Scripting Guide
      • Hands-on Practice
      • Advanced Features
    • Day 4: e-Form Application
      • Server Deployment
      • Viewer In HTML
      • Viewer APIs
      • Prefilling e-Form
      • Submitting e-Form
      • Sending MemoryStream
    • Get Your Certificate
    • Design Guide
      • Dialogue Flow
        • Overview
        • Creating Dialogue Flow
        • Uploading e-Form to Server
        • Running Dialogue Flow
        • Group and Statement
        • Custom Styling
      • Multilingual e-Form
      • Miscellaneous
      • Videosign
        • Videosign User Guide
      • OZ Verifier
        • OZ Verifier Introduction
        • Implementation and Use
        • Requirements
      • HTML5 Editor
        • HTML5 Editor Introduction
        • HTML Editor
        • Requirements and Sample
    • Day 5. Server & Reporting
  • 🌈Server Developer
    • OZ Server Console
    • OZ Scheduler
      • Features
      • Installing OZ Scheduler
      • Scheduler Task
    • Binding & Exporting
      • Overview
      • Export API Example
        • Extract Input Data
        • Export with OZ Server
        • Export with Scheduler
        • Export with Scheduler Task
    • Repository Server
    • Sync Server
      • Overview
      • Installing Sync-Server
        • SSL configration
      • Sample Application
      • Implementation
    • QR Link Mobile Sign
  • 🌈Report Developer
    • Overview
      • About Course
      • Preparation
      • Report Designer Overview
    • Query Design
      • Database Connection
      • Designer Environment
      • Dataset Design
    • Report Design
      • Designer Environment
      • Components
      • Table
      • Master-Detail
      • ODI Parameter
      • CrossTab
      • Chart
  • 🌈MOBILE DEVELOPER
    • Android Native
    • iOS Native
    • TOTO Framework
      • TOTO Overview
      • Sample App Overview
      • Server Application
      • Android Project
  • ⬇️Product Downloads
  • 📚 Product Documentation
  • 📕Technical Guide
  • ⚛️ ReactJS Integration
Powered by GitBook
On this page
  • Add totoframework library to project
  • Configurations
  • res/layout
  • res/menu
  • res/values
  • Activitis
  • Build and Run the App

Was this helpful?

  1. MOBILE DEVELOPER
  2. TOTO Framework

Android Project

A sample app for online and offline

PreviousServer ApplicationNextProduct Downloads

Last updated 3 years ago

Was this helpful?

Add totoframework library to project

  1. First, create the same project as the one we created in the Android Native.

  2. Download oztoto80_android_version.number.tar.gz from 👉

  3. Get the and add it to the libs folder. Of clause, you have to set library dependencies too.

Configurations

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

    <application
        android:allowBackup="true"
        android:hardwareAccelerated="true"
        android:largeHeap="true"
        android:supportsRtl="true"
        android:usesCleartextTraffic="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
        <activity
            android:name="com.forcs.mobile.MainActivity"
            android:configChanges="orientation|screenSize"
            android:exported="true"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.forcs.mobile.OnlineActivity" />
        <activity android:name="com.forcs.mobile.OfflineActivity" />
        <activity android:name="com.forcs.mobile.OZViewerActivity" android:windowSoftInputMode="adjustResize"  android:configChanges = "orientation|screenSize" />
    </application>

    <uses-feature    android:name="android.hardware.camera" />
    <uses-feature    android:name="android.hardware.camera.autofocus" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.NFC" />
</manifest>
apply plugin: 'com.android.application'

android {
    compileSdk 31
    buildToolsVersion "31.0.0"

    defaultConfig {
        applicationId "com.forcs.toto"
        minSdk 21
        targetSdk 31
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            ndk {
                abiFilters 'arm64-v8a'
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
    implementation 'androidx.annotation:annotation:1.3.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation files('libs/ozrv_android.jar')
    implementation files('libs/oztotoframework_android.jar')
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

res/layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_marginTop="200dp"
        android:id="@+id/button1"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:backgroundTint="#29A329"
        android:onClick="online"
        android:text="Server Login"
        android:textAllCaps="false"
        android:textStyle="bold"
        android:textColor="@android:color/white" />

    <Button
        android:id="@+id/button2"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        android:backgroundTint="#0174df"
        android:onClick="offline"
        android:text="Local Forms"
        android:textAllCaps="false"
        android:textStyle="bold"
        android:textColor="@android:color/white" />

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="?attr/actionBarSize">
        <Button
            android:id="@+id/toolbarbtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:layout_gravity="right"/>
    </androidx.appcompat.widget.Toolbar>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_marginTop="10dp"
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="Local Forms"
        android:textStyle="bold"
        android:textSize="16sp" />

    <ListView
        android:padding="5dp"
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="#EAECEE" />
        />

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/label"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dip"
    android:textSize="16dip"
    android:textStyle="bold" >
</TextView>

res/menu

<?xml version="1.0" encoding="utf-8"?>
<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/save"
        android:title="Save"
        app:showAsAction="always" />
</menu>

res/values

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
    <color name="background_dark">#3498DB</color>
</resources>
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

Activitis

package com.forcs.mobile;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestAppPermission(this);
        setContentView(R.layout.activity_main);
    }

    public void online(View view) {
        Intent intent = new Intent(this, OnlineActivity.class);
        startActivity(intent);
    }

    public void offline(View view) {
        Intent intent = new Intent(this, OfflineActivity.class);
        startActivity(intent);
    }

    static boolean requestAppPermission(Context context) {
        if (Build.VERSION.SDK_INT >= 23) {
            String[] need = {Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.READ_PHONE_STATE};
            for (int i = 0; i < need.length; i++) {
                if (context.checkSelfPermission(need[i]) != PackageManager.PERMISSION_GRANTED) {
                    if (context instanceof Activity) {
                        ((Activity) context).requestPermissions(need, 1);
                    }
                    return false;
                }
            }
        }
        return true;
    }

    static void onRequestPermissionsResultCustom(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == 1 && Build.VERSION.SDK_INT >= 23) {
            boolean isallgranted = true;
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                    isallgranted = false;
                }
            }
            if (isallgranted) {
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        onRequestPermissionsResultCustom(requestCode, permissions, grantResults);
    }
}
package com.forcs.mobile;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.Toast;

import androidx.annotation.RequiresApi;

import oz.toto.framework.OZTotoError;
import oz.toto.framework.OZTotoEvent;
import oz.toto.framework.OZTotoEventHandler;
import oz.toto.framework.OZTotoRuntime;
import oz.toto.framework.OZTotoWebView;
import oz.toto.framework.OZTotoWebViewListener;

//import static oz.toto.framework.OZTotoWebView.NAVIGATOR_VISIBLE;

public class OnlineActivity extends Activity {

    FrameLayout parentView = null;
    OZTotoWebView toto = null;
    OZTotoRuntime toto_runtime = null;
    private long backKeyPressedTime = 0;
    private Toast toast;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        parentView = new FrameLayout(this);
        toto = new OZTotoWebView(this);
        OZTotoWebView.setDebugMode(true);
        parentView.addView(toto, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
        setContentView(parentView);
        OZTotoWebView.setDebugMode(true);
        String url = "http://oz.ozeform.io/oz/edu/toto";
        String pageName = "";
        String param = "";

        toto.setTotoWebViewListener(new OZTotoWebViewListener() {

            @Override
            public void onPageLoad(final OZTotoRuntime runtime) {
                runtime.getFramework().addEventListener("_exitApp_", OZTotoFrameworkEvent);
                toto_runtime = runtime;
            }

            @Override
            public void onPageUnload(OZTotoRuntime runtime) {
            }

            @Override
            public void onSelectedMenuButton() {
            }

            @Override
            public void onPageLoadFailure(OZTotoError ozTotoError) {
                home();
            }

            OZTotoEventHandler OZTotoFrameworkEvent = new OZTotoEventHandler() {
                @RequiresApi(api = Build.VERSION_CODES.M)
                @Override
                public void onEvent(OZTotoEvent e) {
                    if (e.eventName.equals("_exitApp_")) {
                        exit();
                    }
                }
            };
        });
        toto.run(url, pageName, param);
    }

    private void exit() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                new AlertDialog.Builder(OnlineActivity.this)
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .setTitle("Online Mode")
                        .setMessage("Do you want to log out?")
                        .setPositiveButton("YES", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                finish();
                            }
                        })
                        .setNegativeButton("NO", null)
                        .show();
            }
        });
    }

    private void home() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                new AlertDialog.Builder(OnlineActivity.this)
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .setTitle("Online Mode")
                        .setMessage("Cannot connect to the server.")
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                finish();
                            }
                        })
                        .show();
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (toto != null) {
            toto.onActivityResult( this, requestCode, resultCode, data);
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onBackPressed() {
        if(toto.canGoBack()) {
            toto.goBack();
        } else{
            if (System.currentTimeMillis() > backKeyPressedTime + 2000) {
                backKeyPressedTime = System.currentTimeMillis();
                toast = Toast.makeText(this, "Press the Back button again to exit.", Toast.LENGTH_SHORT);
                toast.show();
                return;
            }
            if (System.currentTimeMillis() <= backKeyPressedTime + 2000) {
                finish();
                toast.cancel();
            }
        }
    }

}
package com.forcs.mobile;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

// import OZ Viewer API
import java.io.File;

import static android.graphics.Color.WHITE;

public class OfflineActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_offline);

        String tag = "Local storage: ";
        //String path = Environment.getExternalStorageDirectory().toString()+"/toto";
        String path = "data/user/0/com.forcs.toto/toto/";
        Log.d(tag, "Path: " + path);
        File directory = new File(path);
        File[] files = directory.listFiles();

        if (files != null) {
            String[] names = new String[files.length];
            Log.d(tag, "Count: " + files.length);

            for (int i = 0; i < files.length; i++) {
                names[i] = files[i].getName();
                Log.d(tag, "FileName: " + names[i]);
            }
            ArrayAdapter adapter = new ArrayAdapter<String>(this,
                    R.layout.activity_listview, names);
            ListView listView = (ListView) findViewById(R.id.listView);
            listView.setAdapter(adapter);
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int i, long l) {
                    String selectedItem = (String) parent.getItemAtPosition(i);
                    Log.d(tag, "Selected: " + selectedItem);
                    Intent intent = new Intent(view.getContext(), OZViewerActivity.class);
                    intent.putExtra("fileName", selectedItem);
                    startActivity(intent);
                }
            });
        } else {
            exit();
        }
    }

    private void exit() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                new AlertDialog.Builder(OfflineActivity.this)
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .setTitle("Offline Mode")
                        .setMessage("No files found.")
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                finish();
                            }
                        })
                        .show();
            }
        });
    }
}
package com.forcs.mobile;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.content.Intent;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.FrameLayout;
import android.app.AlertDialog;
import android.content.DialogInterface;

// import OZ Viewer API
import oz.api.OZReportAPI;
import oz.api.OZReportCommandListener;
import oz.api.OZReportViewer;

public class OZViewerActivity extends AppCompatActivity {

    // Load OZ Viewer library
    static {
        try {
            System.loadLibrary("skia_android");
            System.loadLibrary("ozrv");
        } catch (Exception e) {
            Log.e("OZRV", "Cannot load OZ Viewer library");
            e.printStackTrace();
        }
    }

    private FrameLayout mLayout; // declare content view for OZ Viewer
    private OZReportViewer mViewer; // declare OZ Viewer
    String ozFile = null;
    String savePath = "/data/user/0/com.forcs.toto/toto";
    String param = "export.applyformat=ozd; ozd.saveall=true; export.mode=silent; export.confirmsave=false; viewer.exportcommand=true; export.path=" + savePath ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mLayout = new FrameLayout(this);
        setContentView(mLayout);
        Intent intent = getIntent();
        ozFile = intent.getExtras().getString("fileName");
        openViewer(ozFile);
    }

    private void openViewer(String ozFile) {
        closeViewer();
        mViewer = OZReportAPI.createViewer(mLayout, ozListener, "connection.openfile=file:///data/user/0/com.forcs.toto/toto/" + ozFile);
    }

    private void closeViewer() {
        if(mViewer != null) {
            mViewer.dispose();
            mViewer = null;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        closeViewer();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_save, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.save:
                param += ";  export.filename=" + ozFile + ";";
                mViewer.ScriptEx("save", param, ";");
                return true;
            default: return super.onOptionsItemSelected(item);
        }
    }

    private void dialogBox(String data) {
        AlertDialog.Builder dialog=new AlertDialog.Builder(this);
        dialog.setMessage(data);
        //dialog.setTitle("OZ e-Form App");
        dialog.setPositiveButton("OK",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        return;
                    }
                });
        AlertDialog alertDialog=dialog.create();
        alertDialog.show();
    }

    OZReportCommandListener ozListener = new OZReportCommandListener() {
        @Override
        public void OZExportCommand(String code, String path, String filename, String pagecount, String filepaths)
        {
            String msg;
            msg = code.equals("1") ? (filename + ":\nSaved successfully.") : ("Error Code: \n" + code);
            dialogBox(msg);
        }
    };

}

Build and Run the App

  1. Connect an Android device to your Windows or Mac and allow USB debugging.

  2. Build and run the App.

🌈
Product Downloads
oztotoframework_android.jar