在Android应用程序上铸造NFT(第2部分)
#web3 #android #区块链 #ipfs

6.设置配置

创建一个新的空白Android项目。在主目录中,创建一个称为 apikey.properties 的文件。然后,我们将添加从前一步获得的值。

WALLET_ADDRESS="0x42703e1F2CCB08583088D96d71d4549Be08b52a7" 
CONTRACT_ADDRESS="0x129Ff5b9D7C128527F3Be5ca5fb4F2E7A991482d" 
WEB_SOCKET_URL="[wss://550b-105-163-1-231.ngrok.io](https://550b-105-163-1-231.ngrok.io)"
SEED="truth manual elephant border predict castle payment suspect mimic insect wish acoustic"
TOKEN_URI=""

进行回顾:

  • 我们通过运行 ganache 命令来获得 wallet_address
  • 我们在运行truffle migrate --network development并从 1_deploy_contract .js e节。
  • 运行 ganache 命令并获得生成的种子后,我们获得了种子

在依赖项下的build.gradle(模块)中,添加_web3j _library。

// Add support for web3j
    implementation 'org.web3j:core:4.8.7-android' 

build.gradle.gradle file的defaultConfig部分中添加配置。

 // Load configuration from the apikey.properties file
 buildConfigField("String", "WALLET_ADDRESS", apikeyProperties['WALLET_ADDRESS'])
 buildConfigField("String", "CONTRACT_ADDRESS", apikeyProperties['CONTRACT_ADDRESS'])
 buildConfigField("String", "WEB_SOCKET_URL", apikeyProperties['WEB_SOCKET_URL'])
 buildConfigField("String", "SEED", apikeyProperties['SEED'])
 buildConfigField("String", "TOKEN_URI", apikeyProperties['TOKEN_URI'])

不要忘记通过将以下行添加到<application标签中的AndroidManifest.xml文件中添加Internet权限。

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

7.开发Android包装器

使用_web3j _library,我们可以将我们的固体文件转换为Java,以便我们调用已写入Solidity文件中的方法。

web3j generate truffle --truffle-json .\build\contracts\lemurNFT.json -o ..\android\app\src\main\java\ -p com.example.lemur

成功运行此命令后,将生成一个新的Java文件LemurNFT.java。将文件靠近 mainActivity.kt 文件。

8.创建UI

用户界面非常简单,我们有一个称为 mint 的按钮。单击按钮时,它在_mainactivity.kt 文件中运行 mintnft _功能。

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="mintNft"
    android:text="@string/button_text"
    tools:layout_editor_absoluteX="161dp"
    tools:layout_editor_absoluteY="407dp" />

整个activity_main.xml文件看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="LemurNFT"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="mintNft"
        android:text="@string/button_text"
        tools:layout_editor_absoluteX="161dp"
        tools:layout_editor_absoluteY="407dp" />

</androidx.constraintlayout.widget.ConstraintLayout>

该应用应该看起来像这样:

Image description

9.添加全局变量

在您的 mainActivity.kt 中添加以下变量为全局。

// inside of any of your application's code
var walletAddress: String = BuildConfig.WALLET_ADDRESS;
var contractAddress: String = BuildConfig.CONTRACT_ADDRESS;
var webSocketUrl: String = BuildConfig.WEB_SOCKET_URL;
var seed: String = BuildConfig.SEED;
var tokenUri: String = BuildConfig.TOKEN_URI;
private lateinit var credentials: Credentials;

此代码从我们的_apikey.properties _file和buildConfig文件加载所有配置文件。

我们还有一个凭证变量,以后将在以后初始初始化,并且可以通过任何函数在全球范围内访问。

10.加载凭据

mainActivity.kt 文件中添加以下代码行。

/***
 * Create credentials from a seed.
 */
fun loadCredentials(){
    val masterKeypair = Bip32ECKeyPair.generateKeyPair(MnemonicUtils.generateSeed(seed, ""))
    val path = intArrayOf(44 or HARDENED_BIT, 60 or HARDENED_BIT, HARDENED_BIT, 0, 0)
    val x = Bip32ECKeyPair.deriveKeyPair(masterKeypair, path)
    this.credentials = Credentials.create(x)
}

这会生成一个键盘(公共和私钥)来签署我们的交易。

11.加载凭据

在mainActivity.kt文件中添加以下代码。

/***
 * Create credentials from a seed.
 */
fun loadCredentials(){
    val masterKeypair = Bip32ECKeyPair.generateKeyPair(MnemonicUtils.generateSeed(seed, ""))
    val path = intArrayOf(44 or HARDENED_BIT, 60 or HARDENED_BIT, HARDENED_BIT, 0, 0)
    val x = Bip32ECKeyPair.deriveKeyPair(masterKeypair, path)
    this.credentials = Credentials.create(x)
}

这会生成一个键盘(公共和私钥)来签署我们的交易。

12.显示回应

将交易发布到区块链后,我们需要显示响应。因此,我们将使用吐司通知。将以下代码添加到mainActivity.kt文件中。

/**
 * Display the response as a toast notification.
 */
private fun showResponse(response: String){

    val duration  = Toast.LENGTH_LONG;
    val toast = Toast.makeText(applicationContext, response, duration);
    toast.show();

}

该函数接入字符串并在烤面包通知中显示。

13.薄荷nft

此处,mINTNFT函数与主用户界面中的按钮绑定。单击按钮后:

  • 凭据将从 loadCredentials()函数中加载。
  • 将创建一个新实例 web3j 实例,该实例将用于连接到节点。
  • 然后,我们加载智能合约是 lemurnft 合同,并提供合同地址,Websocket连接,凭据和交易的气体。
  • 然后,我们将智能合约功能称为薄荷nft,提供钱包地址以铸造NFT,然后 tokenuri
  • 然后,我们使用 log.e *和 *来记录响应,还可以通过吐司通知显示响应。
/**
 * Mint an nft when the mint button is clicked.
 */
fun mintNft(view: View) {
    try {
        loadCredentials();
        val web3j: Web3j = createWeb3j()

        val nft: LemurNFT = LemurNFT.load(contractAddress, web3j, credentials, DefaultGasProvider())
        val transactionReceipt: TransactionReceipt = nft.mintNFT(walletAddress, tokenUri).send()

        Log.e("Response", transactionReceipt.toString());
        showResponse(transactionReceipt.toString());

    } catch (e: Exception){
        e.printStackTrace();
    }
    return;
}

MainActivity.kt然后看起来像这样:

package com.example.lemur

import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import org.web3j.crypto.Bip32ECKeyPair
import org.web3j.crypto.Bip32ECKeyPair.HARDENED_BIT
import org.web3j.crypto.Credentials
import org.web3j.crypto.MnemonicUtils
import org.web3j.protocol.Web3j
import org.web3j.protocol.core.DefaultBlockParameterName
import org.web3j.protocol.core.methods.response.EthGetBalance
import org.web3j.protocol.core.methods.response.TransactionReceipt
import org.web3j.protocol.websocket.WebSocketService
import org.web3j.tx.gas.DefaultGasProvider
import java.math.BigInteger
import java.net.ConnectException


class MainActivity : AppCompatActivity() {

    // inside of any of your application's code
    var walletAddress: String = BuildConfig.WALLET_ADDRESS;
    var contractAddress: String = BuildConfig.CONTRACT_ADDRESS;
    var webSocketUrl: String = BuildConfig.WEB_SOCKET_URL;
    var seed: String = BuildConfig.SEED;
    var tokenUri: String = BuildConfig.TOKEN_URI;
    private lateinit var credentials: Credentials;


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    /**
     * Mint an nft when the mint button is clicked.
     */
    fun mintNft(view: View) {
        try {
            loadCredentials();
            val web3j: Web3j = createWeb3j()

            val nft: LemurNFT = LemurNFT.load(contractAddress, web3j, credentials, DefaultGasProvider())
            val transactionReceipt: TransactionReceipt = nft.mintNFT(walletAddress, tokenUri).send()

            Log.e("Response", transactionReceipt.toString());
            showResponse(transactionReceipt.toString());

        } catch (e: Exception){
            e.printStackTrace();
        }
        return;
    }

    /**
     * Display the response as a toast notification.
     */
    private fun showResponse(response: String){

        val duration  = Toast.LENGTH_LONG;
        val toast = Toast.makeText(applicationContext, response, duration);
        toast.show();

    }

    /**
     * Create a web3j web socket instance from the web socket url.
     */
    private fun createWeb3j(): Web3j {
        val webSocketService = WebSocketService(webSocketUrl, true)
        try {
            webSocketService.connect()
        } catch (e: ConnectException) {
            e.printStackTrace()
        }
        return Web3j.build(webSocketService)
    }

    /***
     * Create credentials from a seed.
     */
    private fun loadCredentials(){
        val masterKeypair = Bip32ECKeyPair.generateKeyPair(MnemonicUtils.generateSeed(seed, ""))
        val path = intArrayOf(44 or HARDENED_BIT, 60 or HARDENED_BIT, HARDENED_BIT, 0, 0)
        val x = Bip32ECKeyPair.deriveKeyPair(masterKeypair, path)
        this.credentials = Credentials.create(x)
    }

}

单击“薄荷”按钮时,一旦编译并运行了应用程序,吐司通知应带有交易收据。

14.结论

恭喜,您已经能够创建NFT智能合约并与Android应用程序进行交互。