NLChat的一周开发总结,从0到1做出了很多聊天功能出来了。 原创

LinMeng林孟
发布于 2024-7-2 00:18
浏览
0收藏

我们的上篇文章:点我访问

很高兴来到这一篇文章的大家,我写这篇文章时是2024年7月1日,先在讲开发总结前,庆祝我们国家建党节103周年一下

今天的内容大体上是对软件的功能更新,还有一些我个人的小插曲,同时也会给大家讲清我们功能的写法。

首先就是第一点,这一点对大家,对Android用户都很重要。一直以来,我们开源的项目,在处理Release发布时,我们的后台操作,经常耗时费力,这很不利于我们++NLChat++聊天软件的开源仓库向大家见面。

那么,来到我们第一个重点了,也就是:自动化构建!

在30号,我打通好了Github Android CI自动化构建程序,省去大家Clone项目再Build的时间的同时,也能同步到Release发布。这期间,我们一直拿主仓库测试,错误了就改错重新试。直到成功,继续看看哪里可以改改,直到代码满意,自动化流程没问题,我们才结束这方面的开发。

Release发行代码:点我查看

name: Android CI Release

on:
  push:
    tags:
      - "v*"

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'
      - uses: gradle/gradle-build-action@v2
        with:
          gradle-version: current
          arguments: assembleRelease
      - uses: r0adkll/sign-android-release@v1
        id: sign_app
        with:
          releaseDirectory: app/build/outputs/apk/release
          signingKeyBase64: ${{ secrets.SIGING_KEY }}
          alias: ${{ secrets.ALIAS }}
          keyStorePassword: ${{ secrets.KEY_PASSWORD }}
          keyPassword: ${{ secrets.KEY_PASSWORD }}
        env:
          BUILD_TOOLS_VERSION: "34.0.0"
      - run: mv ${{steps.sign_app.outputs.signedReleaseFile}} NLChat_$GITHUB_REF_NAME.apk
      - uses: ncipollo/release-action@v1
        with:
          artifacts: "*.apk"
          token: ${{ github.token }}
          generateReleaseNotes: true

我们NLChat软件,从发行的开始使用教新的Gradle编译、Java17主流版本、Android SDK 34版本打包签名,确保我们的软件在新设备上运行不出问题。至于隔壁Debug的自动化流程,我就不在此放出来了。

来到第二点,不知道大家有没有注意,我们的README有了许多变化。

作为一个认真搞开源程序的我们,在开发的途中走在前人走过的路上,永远都是我们的最佳必经之路,所以,我们添加了众多作者们(包括Github官方)的开源协议。向您们表达感谢。

接下来就来到我们的重头戏了,我们做好了SQLite部分相关功能。

7月1号当天,我在上午推送了1.2.16这个版本。点我下载体验旧版

该版本作为我们第一次公开展示聊天记录保存的细节,其实就是用到了SQLite来做到的功能。接下来就是代码讲解环节了。

如果我们想在Android上使用SQLite,本质上跟电脑上的SQL、MongoDB一样,我们的第一步永远都是添加支持,第二步添加数据库文件,第三步++理清数据库框架++,第四步增删改查,虽然我目前只写到“增”,但也快了,该有的功能都会如期而至公开开源出来的。

首先,让我们创建一个类,这个类,必须包括上面的“一二三四”四个操作的函数,并保留“增”、“查”这些接口。那么,代码将是如下写法:

public class SQLiteDataBaseAPP {

    SQLiteDatabase sqLiteDataBaseForAPP,sqLiteDataBaseForUser,sqLiteDataBaseForChat,sqLiteDataBaseForDevice;

    protected SQLiteDataBaseAPP() { }
    public static SQLiteDataBaseAPP SQLiteData() { return SQLiteDataBaseAPP.data.shuju; }
    protected static class data { private static final SQLiteDataBaseAPP shuju = new SQLiteDataBaseAPP(); }

    public void CreateSql(String SDPath) {
        sqLiteDataBaseForAPP = SQLiteDatabase.openOrCreateDatabase(SDPath + "/NLChat.db",null);
        sqLiteDataBaseForUser = SQLiteDatabase.openOrCreateDatabase(SDPath + "/NLChatUser.db", null);

        sqLiteDataBaseForChat = SQLiteDatabase.openOrCreateDatabase(SDPath + "/NLChatChat.db",null);
        createChatTable();
        sqLiteDataBaseForDevice = SQLiteDatabase.openOrCreateDatabase(SDPath + "/NLChatDevice.db",null);
    }


    private void createChatTable() {
        String TABLE_CREATE =
                "CREATE TABLE IF NOT EXISTS messages (" +
                        "_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                        "message TEXT, " +
                        "sender TEXT, " +
                        "timestamp TEXT);";
        sqLiteDataBaseForChat.execSQL(TABLE_CREATE);
    }

    public void saveMessageToDatabase(String message, String sender, String timestamp) {
        ContentValues values = new ContentValues();
        values.put("message", message);
        values.put("sender", sender);
        values.put("timestamp", timestamp);
        sqLiteDataBaseForChat.insert("messages", null, values);
    }

    public Cursor getAllMessages() {
        return sqLiteDataBaseForChat.query("messages", null, null, null, null, null, "timestamp ASC");
    }
}

通过saveMessageToDatabase(…),这个方法,我想大家都能知道我目前做的数据库多简单了吧,如图所示,我们就保存了用户的消息、谁发送谁接收和时间戳。

NLChat的一周开发总结,从0到1做出了很多聊天功能出来了。-鸿蒙开发者社区

你想问我为什么现阶段用明文存储?我的答案其实很简单:目前SQL文件存储位于/data/user/0/软件包包名/files这个文件夹下,该路径为Android系统权限锁死的地方,除非开发者或用户对手机进行了ROOT获取后提权访问该文件夹获取SQLite文件,否则通过其他途径无法获得该文件。

当然,这一次更新,不止有SQLite这个功能,还有滚动消息功能。

滚动消息,顾名思义,就是对已经存在UI屏幕上许久的聊天文本,我们其实可以通过代码来做到被下一句消息顶替的。之所以之前我们没有这个功能,而是现在才有这个功能,还是因为我感觉如果任由TextView一直显示大量之前的信息,观赏性阅读性会变差。

所以,我在ChatUtils类里,添加了boolean变量,这项功能目前还仅仅是做到代码里修改是否开启,后续会集成进UI里。

public class ChatUtils {
    //这里设置的是UI相关,是否做到消息滚动展示在UI上,而不是全部展示,全部展示会占用大量UI资源
    private static final boolean scrollingMessages = true; // 控制是否启用滚动消息功能
    ......

    //控制是否启用滚动消息功能
    public static boolean isScrollingMessages() { return scrollingMessages; }
    ......
}

添加了这个boolean变量,我们接下来的软件是否用到这个功能就取悦于我们手动true or false了,那么,我们也要对ReadData和SendData读和发送相关代码,做进一步的修改,确保我们想要的功能可控开关还能实现,读取相关代码如下:

//处理完再打印到UI上
            runOnUiThread(() -> {
                saveMessageToDatabase(processedString, "User");
                if (ChatUtils.isScrollingMessages()) {
                    if (serverMessageQueue.size() >= MAX_MESSAGES * 3) {
                        serverMessageQueue.poll();
                    }
                    serverMessageQueue.add(processedString);
                    updateServerTextView();
                } else {
                    NearLinkServerText.append(processedString);
                    if (NearLinkServerText.length() > 2048) {
                        String str = NearLinkServerText.getText().toString().substring(NearLinkServerText.getText().length() - 1024, NearLinkServerText.getText().length());
                        NearLinkServerText.setText("");
                        NearLinkServerText.append(str);
                    }
                }
            });

发送相关,我们也有做修改,本质上,就是是true(启用)后,我们的MessageQuete这个LinkedList变量,相当于是一个队列存储俩端消息。发行队列满了,则移除最早的消息,再添加新消息到队列。发送相关代码也是一样,代码如下:

runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    saveMessageToDatabase(TextOfClient, "Me");
                    if (ChatUtils.isScrollingMessages()) {
                        if (clientMessageQueue.size() >= MAX_MESSAGES) {
                            clientMessageQueue.poll(); // 移除最早的消息
                        }
                        clientMessageQueue.add(TextOfClient);
                        updateClientTextView();
                    } else {
                        NearLinkClientText.append(TextOfClient);
                        if (NearLinkClientText.length() > 2048) {
                            String str = NearLinkClientText.getText().toString().substring(NearLinkClientText.getText().length() - 1024, NearLinkClientText.getText().length());
                            NearLinkClientText.setText("");
                            NearLinkClientText.append(str);
                        }
                    }
                }
            });

借助生活中便捷的灵感,我们这款NLChat也开发了一个小功能:添加聊天剪贴板。

这个功能是为什么会做出来的呢?是因为我发现,我们在使用多部手机时,可以做到把验证码发给另一部设备,自动写入剪贴板后粘贴到软件上输入验证码完成登录等验证。那么这个功能就是因为这个idea发明了出来,代码如下:

//聊天进入剪贴板
                if (ChatUtils.isClipMessages()) {
                    // 提取四位和六位数字
                    Pattern pattern = Pattern.compile("\\b\\d{4}\\b|\\b\\d{6}\\b");
                    Matcher matcher = pattern.matcher(completeSecondData);
                    while (matcher.find()) {
                        String foundNumber = matcher.group();
                        extractedNumbers.append(foundNumber).append("\n");
                    }

                    // 将提取到的数字复制到剪贴板
                    if (extractedNumbers.length() > 0) {
                        ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
                        ClipData clip = ClipData.newPlainText("extractedNumbers", extractedNumbers.toString().trim());
                        clipboard.setPrimaryClip(clip);
                        SnackBarToastForDebug("提取到疑似验证码,已复制到剪贴板!","推荐去粘贴",0,Snackbar.LENGTH_LONG);
                    }
                }

目前这个功能可能会遇到Bug,我会在后面修复相关问题。

完成了这么多功能,我还修复了SQL相关的Bug,之前的代码可能存在SQL写入空行的逻辑问题。

如图就是我在Test时遇到的情况:

NLChat的一周开发总结,从0到1做出了很多聊天功能出来了。-鸿蒙开发者社区

那么,这样的问题该怎么解决呢?其实很简单,检测添加进SQL时如果没有内容则不添加不就好了,代码如下:

    private void saveMessageToDatabase(String message, String sender) {
        //检索是否有空消息,串口通讯时常有相关问题
        if (message == null || message.trim().isEmpty()) {
            return;
        }
        //如果有消息再保存,上面是没消息不予保存
        ......
    }

写到最后,来些轻松的话题,这么多天,我不但在添加软件功能修复Bug,还有做着许多测试呢。

NLChat的一周开发总结,从0到1做出了很多聊天功能出来了。-鸿蒙开发者社区

第一张图是做压力测试呢OvO,我自己是很满意这样的单向通信,当然,我是用一款无障碍自动点击做到这么点击的(40ms的一次click)

NLChat的一周开发总结,从0到1做出了很多聊天功能出来了。-鸿蒙开发者社区

NLChat的一周开发总结,从0到1做出了很多聊天功能出来了。-鸿蒙开发者社区

还有很多所谓的开发瞬间我就因为篇幅不多放了,希望大家见谅。

最后一个好消息,我们这款NLChat软件,已经报名参加了星闪开发者体验官活动。

已经报名了哦,那么,我们这款软件的开发周期,将会延长到比赛结束,请大家不必担心功能问题。

End.

GitHub安卓仓库
Gitee安卓仓库

2024.7.2

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
NLChat_v1.2.52.2024.0701.apk 20.69M 9次下载
已于2024-7-2 03:17:44修改
3
收藏
回复
举报
2条回复
按时间正序
/
按时间倒序
wx5f7d8b46bc82c
wx5f7d8b46bc82c

学到了,感谢分享。

回复
2024-7-2 01:43:29
红叶亦知秋
红叶亦知秋

各个环节确实都不容易

1
回复
2024-7-2 09:56:28
回复
    相关推荐