DQtech Column | Learn from DEX about PlatON Application Development – Android (I)

Author Dex_DQT

From now, we will begin to learn how to build the Android version of Digging. In this chapter, we will build the environment and create the function to getting the wallet balance.

Build Project

This article uses koltin for development, and the IDE is Android. Open Android studio and create a new project.

(K$CE3NU9Y8IKHPHQ5M81S

Here we choose Empty Activity

PV7W40Z6P{70P9(}$JZKG(E

The development language is koltin, and the minimum supported SDK is API 21

After the project is created, the directory is as follows:

SMGT3(R~4%J%79Q_{E`QUE

Then we introduce the SDK of Platon’s Android version

Open build.gradle in app directory, the content is as follows:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
    compileSdk 31

    defaultConfig {
        applicationId "com.digquant"
        minSdkVersion 21
        targetSdkVersion 31
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

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

    buildFeatures {
        viewBinding true
    }

    dataBinding {
        //noinspection DataBindingWithoutKapt
        enabled = true
    }
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
    android.applicationVariants.all {
        variant ->
            variant.outputs.all {
                //在这里修改apk文件名
                outputFileName = "digging.apk"
            }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    splits {
        abi {
            enable true
            reset()
            universalApk true
        }
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }

}

dependencies {

    implementation 'com.google.android.material:material:1.4.0'
    // 引入platON的jar包
    implementation 'com.platon.client:core:0.13.0.2-android'
    implementation 'com.platon.client:crypto:0.13.0.2-android'
}

Then open the outermost settings.gradle file, as shown below:

1640787260(1)

Add the warehouse address of PlatON, as follows:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        maven { url "https://jitpack.io" }
        maven { url "https://sdk.platon.network/nexus/content/groups/public/" }
        
        mavenCentral()
        jcenter() // Warning: this repository is going to shut down soon

    }
}
rootProject.name = "Digging"
include ':app'

Next, create the libs directory in the app directory and copy the libscrypt.so to the modified directory, as shown in the following picture:

1640787374(1)

Set it to support arm64 and x86. Readers can delete unnecessary platforms by themselves.

Finally, add the permission to use the network in the AndroidManifest.xml. The code is as follows:

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

    <!-- 访问网络,网络定位需要上网-->
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher" 
        android:label="@string/app_name"
        android:usesCleartextTraffic="true"

        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Digging">
        <activity
            android:name=".activity.MainActivity"
            android:screenOrientation="fullSensor"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

So far, the construction of the project has been completed.

编写代码

Creat an api vfolder in the com.digquant, then add PlatonApi, as shown in follow:

1640787533(1)

As its’ name shows, All interaction interfaces with the Platon node are placed in PlatonApi. Its code is as follows:

class PlatonApi {
    //
    companion object {
        // 测试节点地址
        const val url: String = "http://35.247.155.162:6789"
        //连接超时时间
        const val TRANSACTION_SEND_CONNECT_TIMEOUT: Long = 10000
        // 读取超时
        const val TRANSACTION_SEND_READ_TIMEOUT: Long = 50000
        // PlatonApi为单例
        val platonApi: PlatonApi = PlatonApi()
    }

    // 手续费
    private val GasPrice: BigInteger = BigInteger.valueOf(2000000000000L)
    // 手续费上线
    private val GasLimit: BigInteger = BigInteger.valueOf(99999L)
    // 手续费类
    var gasProvider = ContractGasProvider(GasPrice, GasLimit)
    // 和PlatON通讯的对象
    var mWeb3j: Web3j = Web3jFactory.build(
        HttpService(
            url, OkHttpClient().newBuilder()
                .connectTimeout(
                    TRANSACTION_SEND_CONNECT_TIMEOUT,
                    TimeUnit.MILLISECONDS
                )
                .readTimeout(
                    TRANSACTION_SEND_READ_TIMEOUT,
                    TimeUnit.MILLISECONDS
                )
                .build(), false
        )
    );
    /**
     * 获取余额
     */
    fun GetBalance(walletAddress: String): PlatonGetBalance {
        return mWeb3j.platonGetBalance(
            walletAddress,
            DefaultBlockParameterName.LATEST
        ).send()
    }
}

It is an soly example to realize the construction of handling fee class through companion method.
The naming rules of functions in this project refer to Golang: the first letter of public functions are uppercase, and others are lowercase. Because the function to obtain the specified wallet balance here is a public function, so it should be GetBalance.
Then write the interface. Open activity_main.xml in res/layout, as shown:

1640788019(1)

Code as follows:

<?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"
    android:padding="10dp"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:text="钱包地址:" />

        <EditText
            android:id="@+id/walletAddress"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请输入要查询的钱包地址" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:text="当前余额:" />

        <TextView
            android:id="@+id/balance"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
    
    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="获取" />

</LinearLayout>

The interface would be like:

6065862C5F08A9E7E65F69BB492E835B

Then add MainActivity into com.digquant.activity.
1640788194(1)

Code as follows:

class MainActivity : AppCompatActivity() {

    /**
     * 使用binding
     */
    lateinit var binding: ActivityMainBinding

    /**
     * 创建handler
     */
    lateinit var handler: Handler

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 构建布局
        val inflater = LayoutInflater.from(this)
        binding = ActivityMainBinding.inflate(inflater, null, false);
        setContentView(binding.root)
        
        handler = Handler();

        initEvent();

    }

    /**
     * 初始化时间
     */
    private fun initEvent() {

        binding.btn.setOnClickListener {
            val walletAddress = binding.walletAddress.text.toString()
            /**
             * 因此platonApi调用Http的方式都是同步的
             * 而在UI线程不能发起Http调用因此需要在子线程调用
             * 把调用任务放在线程池
             */
            ThreadPoolUtil.AddTask {
                /**
                 * 获取platonApi对象
                 */
                val platonApi = PlatonApi.platonApi
                val platonBalance = platonApi.GetBalance(walletAddress)

                /**
                 * 获取的balance单位为Von,要手动转为LAT
                 */
                val lat =
                    Convert.fromVon(BigDecimal(platonBalance.balance), Convert.Unit.LAT).toDouble();
                // 通过handler讲balance传回UI线程
                handler.post {
                    binding.balance.text = lat.toString()
                }
            }
        }
    }
}

Note that Platon’s Api calls to Http are synchronous, so they cannot be used in the UI thread and need to be placed in a sub-thread. To avoid the need to create a sub-thread for each call, we will build a thread pool here.
Creat com.digquant.util and add ThreadPoolUtilin it, code as follows:

package com.digquant.util

import java.util.concurrent.LinkedBlockingDeque
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit

class ThreadPoolUtil {
    companion object {
        private val executor = ThreadPoolExecutor(
            2,
            10,
            10 * 60,
            TimeUnit.SECONDS,
            LinkedBlockingDeque()
        )
        fun AddTask(runnable: Runnable?) {
            executor.execute(runnable)
        }
    }
}

Finally, enter this adress in the app: lat1zrq89dhle45g78mm4j8aq3dq5m2shpu56ggc6e0

Than tou can see the balance, as dhown in the follow:

193F6A80938B6F1DDB743D1058763F15

The browser would found the balance as follows:

Y7H{CX3$Y9H(D@O(YTJL(DU

Same as we got.

Well, that’s all of this chapter.

The URL of github: https://github.com/DQTechnology/Platon_DevGuideProject

This article is reproduced from https://forum.latticex.foundation/t/topic/5948

Like (0)
Previous February 9, 2022 23:53
Next February 14, 2022 16:29

相关推荐

Leave a Reply

Please Login to Comment