18、移动应用开发:打造简易移动信使应用

移动应用开发:打造简易移动信使应用

1. 开发前的准备

在开发移动应用时,如果需要运行特定于 Cordova 的代码,可以使用以下可用标志来运行:

if(Meteor.isCordova) {
    // 这里写你的代码
}

接下来,我们将创建一个简单的移动信使应用——TellMe。该应用的主要功能是检查已登录用户的联系人列表,若其中有使用该应用的联系人,则将其显示在列表中,用户可从此处开始与他们进行一对一的消息交流。为了便于构建该应用,我们将问题拆解如下:
1. 提供登录界面,登录时将必要信息(如电话号码)保存到服务器数据库。
2. 登录后,用户应能看到使用该应用的联系人,这需要访问用户的联系人信息。获取联系人后,通过与数据库对比,检查其中是否有使用该应用的联系人,但不将联系人信息存储在数据库中。
3. 若有匹配的联系人,应用应显示这些联系人的姓名和电话号码。
4. 点击列表中的某个联系人,应将用户带到消息界面,用户可在此输入并发送消息给对方。
5. 对方应能接收消息。

创建一个名为 TellMe 的 MeteorJS 应用,并为其添加 Android 和 iOS 平台。

2. 登录界面的搭建

我们允许用户使用电子邮件进行注册。为了简化操作,先使用 accounts 包提供的常规注册方式,后续可自行添加手机号码注册功能。

操作步骤如下
1. 为应用添加 accounts - password 和 accounts - ui 包。
2. 在应用根目录下创建 lib、server 和 client 目录,分离服务器代码和客户端代码。
3. 清理现有样板代码,删除 .css 和 .js 文件,仅保留 .html 文件,并从 HTML 文件中删除与 hello 模板相关的代码,包括 body 标签内的内容。

为了维护应用状态和导航,我们使用 FlowRouter 进行路由管理,Blaze - Layout 进行布局管理。

meteor add kadira:flow-router
meteor add kadira:blaze-layout

在 lib 目录下创建 router.js 文件,添加以下首页路由:

FlowRouter.route('/', {
    action: function() {
        if(!Meteor.userId()) {
            BlazeLayout.render("loginLayout");
            Accounts._loginButtonsSession.set('dropdownVisible', true);
        } else {
            FlowRouter.go("/profile");
        }
    }
});

在 client 目录下创建 layouts 目录,用于存放所有与布局相关的文件。在 layouts 目录下创建 loginLayout.html 文件,并添加以下模板代码:

<template name="loginLayout">
    <div class="loginContainer">
        {{> loginButtons}}
    </div>
</template>

为了将登录表单居中显示,在 client 目录下创建 stylesheets 目录,并添加 login.css 文件,添加以下 CSS 代码:

/** reset **/
body {
    padding: 0;
    margin: 0;
    background: #f6f6f6;
    height: 100vh;
}
/** reset end **/
/** Login Section **/
.loginContainer {
    height: 100vh;
    display: flex;
    flex: 1;
    align-items: center;
    justify-content: center;
    flex-direction: column;
}
.loginContainer header {
    font-size: 2em;
    font-style: italic;
}
.loginContainer .login - close - text, .loginContainer .login - link - text {
    display: none;
}
.loginContainer .accounts - dialog {
    display: block;
    margin: 0;
}
.loginContainer #login - dropdown - list {
    position: static;
}
.loginContainer .additional - link - container {
    display: inline - block;
    width: 49%;
    text-align: right;
}
.loginContainer .additional - link - container a {
    float: none !important;
}
.loginContainer #signup - link {
    text-align: left !important;
}
/** Login Section Ends **/

此时,登录界面已准备就绪。在浏览器中查看,表单将居中显示。若想在移动设备或模拟器上查看应用效果,停止应用后重新在移动设备或模拟器上运行即可。

在应用启动时,会出现一个带有黑色背景、白色星星闪烁且底部有 MeteorJS 标志的屏幕,这就是移动应用启动时常见的闪屏。MeteorJS 在为移动平台打包应用时,会默认添加这些图片和图标。若想自定义闪屏和应用图标,可通过在应用根目录下创建 mobile - config.js 文件来实现,示例配置如下:

App.info({
    id: 'com.meteor.mobile.myMessenger',
    name: 'myMessenger',
    description: 'Send message to your contacts',
    author: 'Meteor User',
    email: 'noreply@mymessenger.com',
    website: 'http://mymessenger.com'
});
App.icons({
    // iOS
    'iphone': 'resources/icons/icon - 60x60.png',
    'iphone_2x': 'resources/icons/icon - 60x60@2x.png',
    'iphone_3x': 'resources/icons/icon - 60x60@3x.png',
    'ipad': 'resources/icons/icon - 76x76.png',
    'ipad_2x': 'resources/icons/icon - 76x76@2x.png',
    // Android
    'android_ldpi': 'resources/icons/icon - 36x36.png',
    'android_mdpi': 'resources/icons/icon - 48x48.png',
    'android_hdpi': 'resources/icons/icon - 72x72.png',
    'android_xhdpi': 'resources/icons/icon - 96x96.png'
});
App.launchScreens({
    // iOS
    'iphone': 'resources/splash/splash - 320x480.png',
    'iphone_2x': 'resources/splash/splash - 320x480@2x.png',
    'iphone5': 'resources/splash/splash - 320x568@2x.png',
    'iphone6': 'resources/splash/splash - 375x667@2x.png',
    'iphone6p_portrait': 'resources/splash/splash - 414x736@3x.png',
    'iphone6p_landscape': 'resources/splash/splash - 736x414@3x.png',
    'ipad_portrait': 'resources/splash/splash - 768x1024.png',
    'ipad_portrait_2x': 'resources/splash/splash - 768x1024@2x.png',
    'ipad_landscape': 'resources/splash/splash - 1024x768.png',
    'ipad_landscape_2x': 'resources/splash/splash - 1024x768@2x.png',
    // Android
    'android_ldpi_portrait': 'resources/splash/splash - 200x320.png',
    'android_ldpi_landscape': 'resources/splash/splash - 320x200.png',
    'android_mdpi_portrait': 'resources/splash/splash - 320x480.png',
    'android_mdpi_landscape': 'resources/splash/splash - 480x320.png',
    'android_hdpi_portrait': 'resources/splash/splash - 480x800.png',
    'android_hdpi_landscape': 'resources/splash/splash - 800x480.png',
    'android_xhdpi_portrait': 'resources/splash/splash - 720x1280.png',
    'android_xhdpi_landscape': 'resources/splash/splash - 1280x720.png'
});
// 设置 PhoneGap/Cordova 偏好
App.setPreference('BackgroundColor', '0xff0000ff');
App.setPreference('HideKeyboardFormAccessoryBar', true);
App.setPreference('Orientation', 'default');
App.setPreference('Orientation', 'all', 'ios');

这个配置几乎涵盖了移动设备所有可能的尺寸、分辨率和方向。同时,我们还可以在这个文件中添加 Cordova/PhoneGap 特定的偏好设置。

在移动设备上,无需用户干预或只需少量操作,就可以轻松获取大量信息,如电子邮件、手机号码、联系人、通话记录、Wi - Fi 信息、图库照片、相机或其他媒体访问权限等。Cordova 为获取这些信息提供了便利。若要从 MeteorJS 与 Cordova 进行交互,需用特定平台的语言编写所需功能的访问代码,并将其暴露在 JavaScript 中。许多常见的使用场景已被编写成插件,可从 JavaScript 环境中调用。可访问 http://cordova.apache.org/plugins 搜索所需插件。在 MeteorJS 中,需将插件作为 Cordova 包添加到应用中,后续在获取用户联系人信息时会详细介绍。

3. 个人资料界面的实现

为了能依据电话号码在用户数据库中进行匹配,我们需要获取用户的电话号码。虽然可以使用 Cordova 插件来获取电话号码,但这些方法并不十分可靠。因此,我们提供一个简单的界面,让用户自行输入姓名和电话号码,应用会将这些信息作为用户的个人资料进行存储。

具体操作如下
1. 在 router.js 文件中添加以下个人资料路由:

FlowRouter.route("/profile", {
    action: function() {
        Accounts._loginButtonsSession.set('dropdownVisible', false);
        if(Meteor.userId()) {
            BlazeLayout.render("layout", {main: "profileForm"});
        } else {
            FlowRouter.go("/");
        }
    }
});
  1. 由于无法在路由中直接访问 Meteor.user(),我们设置一个跟踪器,根据 Meteor.user() 的返回值将用户重定向到相应的路由:
Tracker.autorun(function() {
    if(!Meteor.user()) {
        FlowRouter.go("/");
    } else {
        var user = Meteor.user();
        if (user && user.profile && user.profile.phone) {
            FlowRouter.go("/contacts");
            return false;
        }
        FlowRouter.go("/profile");
    }
});
  1. 在 layouts 目录下创建 layout.html 文件,添加以下布局模板代码:
<template name="layout">
    <div class="profileContainer">
        <div class="header">
            <div class="logo">TellMe</div>
            {{> loginButtons}}
        </div>
        <div class="container well well - lg">
            {{> Template.dynamic template=main}}
        </div>
    </div>
</template>
  1. 在 client 目录下创建 profile 目录,用于存放与个人资料相关的代码。在 profile 目录下创建 profileForm.html 和 profileForm.js 文件,并分别添加以下模板和辅助代码:
<template name="profileForm">
    <form class="action">
        <div class="form - group">
            <label for="name">Name</label>
            <input type="text" class="form - control" id="name" placeholder="Name">
        </div>
        <div class="form - group">
            <label for="phone">Phone</label>
            <input type="text" class="form - control" id="phone" placeholder="Phone">
        </div>
        <button type="submit" class="btn btn - default">Submit</button>
    </form>
</template>
Template.profileForm.events({
    "submit form": function(e) {
        e.preventDefault();
        var name = e.target.querySelector("#name").value;
        var phone = e.target.querySelector("#phone").value;
        Meteor.call("updateProfile", name, phone, function(error, result) {
            if(!error) {FlowRouter.go("/contacts");}
        });
    }
});
  1. 在 server 目录下创建 methods.js 文件,添加以下方法来保存个人资料:
Meteor.methods({
    updateProfile: function(name, phone) {
        Meteor.users.update({_id: Meteor.userId()}, {$set: {profile: {name: name, phone: phone}}});
    }
});

为了简化代码,上述代码片段中未添加验证逻辑,但在实际应用中,添加适当的验证是非常重要的。成功保存个人资料后,用户将被重定向到联系人页面,真正的功能实现也将从这里开始。

4. 联系人界面的开发

为了显示使用该应用的联系人,我们需要添加路由、模板和模板辅助函数。

操作步骤如下
1. 在 router.js 文件中添加以下联系人路由:

FlowRouter.route('/contacts', {
    action: function() {
        if(!Meteor.userId()) {
            FlowRouter.go("/");
        } else {
            Accounts._loginButtonsSession.set('dropdownVisible', false);
            BlazeLayout.render("layout", {main: "contacts"});
        }
    }
});
  1. 在 client 目录下创建 contacts 目录,用于存放与联系人相关的模板和辅助函数。在 contacts 目录下创建 contacts.html 和 contactsHelper.js 文件,并在 contacts.html 文件中添加以下联系人模板代码:
<template name="contacts">
    <div class="contacts">
        {{#if isLoading}}
        <div class="loading">Loading...</div>
        {{else}}
            {{#if isContactsAvailable}}
            <ul class="list">
                {{#each contacts}}
                <li>
                    <div>{{this.name}}</div>
                    <div>{{this.phone}}</div>
                </li>
                {{/each}}
            </ul>
            {{else}}
            <div class="text - center">No contact available</div>
            {{/if}}
        {{/if}}
    </div>
</template>
  1. 在显示该模板之前,我们需要读取设备联系人信息,将其与应用数据库进行比对,获取匹配的用户并将其显示在列表中。这里我们使用 cordova - plugin - contactsPhoneNumer 插件来读取联系人信息。安装该插件的命令如下:
meteor add cordova:cordova - plugin - contactsPhoneNumer@ https://github.com/dbaq/cordova - plugin - contacts - phone - numbers.git#6fa2e27afa3c54c18e88eb8ba0649dd4e4200ce2

添加插件时,需在插件名称前加上 cordova:,后面跟上插件名称,再加上 @ 和版本号或插件的 Git URL。若使用 Git URL,必须指定要使用的提交哈希。可通过 meteor list 命令查看已添加的 Cordova 插件,使用 meteor remove cordova:cordova - plugin - contactsPhoneNumer 命令移除插件。在添加插件前,需检查插件支持的平台,部分插件可能只针对 Android 或 iOS 其中一个平台编写,因此在使用前需在所有目标平台上进行测试。

  1. 在 contactsHelper.js 文件中添加以下回调函数,用于在 contacts 模板创建时读取联系人信息:
Template.contacts.onCreated(function() {
    var _this = this;
    this.contacts = [];
    this.loadingContacts = new ReactiveVar(true);
    if (Meteor.isCordova) {
        navigator.contactsPhoneNumbers.list(function(contacts) {
            var contacts = _.filter(contacts, function(eachContact) {
                if (eachContact.phoneNumbers.length && eachContact.phoneNumbers[0].type === "MOBILE") {
                    eachContact.phone = eachContact.phoneNumbers[0].number;
                    return true;
                }
            });
            Meteor.call("checkContacts", contacts, function(error, result) {
                if(!error) {
                    _this.contacts = result;
                }
                _this.loadingContacts.set(false);
            });
        }, function(error) {
            _this.loadingContacts.set(false);
            console.error(error);
        });
    } else {
        _this.loadingContacts.set(false);
    }
});

在上述代码中,我们在模板实例级别定义了两个变量:contacts 数组用于存储与数据库匹配后的联系人信息;loadingContacts 是一个响应式变量,用于在应用进行匹配操作时显示加载提示。我们仅在设备环境下(即 Meteor.isCordova 为 true 时)获取联系人信息,若在桌面浏览器中查看联系人页面,将不会显示加载提示,而是直接显示空列表。

插件暴露了 navigator.contactsPhoneNumbers.list 方法,该方法接受一个成功回调和一个失败回调。大多数插件都会采用这种方式暴露方法。不同的插件作者可能会以不同的方式暴露访问原生功能的接口,如直接将方法附加到 window 对象、在 window.plugins 下进行命名空间管理或添加到 navigator 对象等,因此在使用插件时,需仔细阅读插件文档以了解如何通过暴露的接口访问功能。

在成功回调中,我们过滤出有手机号码的联系人,并将手机号码发送到服务器进行匹配操作。服务器端的 checkContacts 方法如下:

checkContacts: function(contacts) {
    contacts = contacts || [];
    if(contacts.length) {
        var numbers = _.map(contacts, function(eachContact) {
            return eachContact.phone;
        });
        return Meteor.users.find({"profile.phone": {$in: numbers}}).fetch().map(function(user) {
            return _.extend(user.profile, {_id: user._id});
        });
    } else {
        return [];
    }
}

将上述服务器方法添加到 methods.js 文件中。该方法使用 $in 操作符构建一个 MongoDB 查询,用于检查用户数据库中 profile.phone 字段是否包含传入的手机号码。匹配的文档将返回其 _id,后续可用于导航。

在模板的 onCreated 回调中调用该服务器方法后,匹配的联系人信息将被赋值给 this.contacts 数组,并在模板中显示。同时,在成功和失败回调中都将 loadingContacts 标志设置为 false,以移除加载提示。

最后,在 contactsHelper.js 文件中添加以下模板辅助函数和事件处理函数:

Template.contacts.helpers({
    isLoading: function() {
        return Template.instance().loadingContacts.get();
    },
    isContactsAvailable: function() {
        return !!Template.instance().contacts.length;
    },
    contacts: function() {
        return Template.instance().contacts;
    }
});
Template.contacts.events({
    "click .list li": function(e) {
        FlowRouter.go("/messenger/"+this._id);
    }
});

通过以上步骤,我们完成了联系人界面的开发,用户可以看到使用该应用的联系人列表,点击联系人即可进入消息界面进行消息交流。

综上所述,我们通过一系列的步骤,从登录界面、个人资料界面到联系人界面的开发,逐步构建了一个简单的移动信使应用。在开发过程中,我们充分利用了 MeteorJS 和 Cordova 的功能,实现了用户注册、个人资料管理和联系人信息展示等功能。同时,我们也了解了如何使用 Cordova 插件来获取移动设备的原生功能,以及如何在 MeteorJS 中进行路由管理和布局渲染。希望这些内容能为你开发移动应用提供一些帮助和启示。

移动应用开发:打造简易移动信使应用

5. 消息界面的实现

当用户点击联系人列表中的某个联系人时,会进入消息界面。我们需要为消息界面添加路由、模板和相应的逻辑。

操作步骤如下
1. 在 router.js 文件中添加消息路由:

FlowRouter.route('/messenger/:contactId', {
    action: function(params) {
        if (!Meteor.userId()) {
            FlowRouter.go("/");
        } else {
            Accounts._loginButtonsSession.set('dropdownVisible', false);
            BlazeLayout.render("layout", {main: "messenger"});
        }
    }
});

这里的 :contactId 是动态参数,用于标识要与之聊天的联系人。

  1. client 目录下创建 messenger 目录,在该目录下创建 messenger.html messengerHelper.js 文件。在 messenger.html 中添加消息模板代码:
<template name="messenger">
    <div class="messenger">
        <div class="messages">
            {{#each messages}}
            <div class="message">
                <div>{{this.senderName}}</div>
                <div>{{this.content}}</div>
            </div>
            {{/each}}
        </div>
        <form class="send - message">
            <input type="text" id="message - input" placeholder="Type your message">
            <button type="submit">Send</button>
        </form>
    </div>
</template>
  1. messengerHelper.js 中添加模板辅助函数和事件处理函数:
Template.messenger.helpers({
    messages: function() {
        // 这里需要实现获取消息的逻辑,假设我们有一个 Messages 集合
        return Messages.find({
            $or: [
                {senderId: Meteor.userId(), receiverId: FlowRouter.getParam('contactId')},
                {senderId: FlowRouter.getParam('contactId'), receiverId: Meteor.userId()}
            ]
        });
    }
});

Template.messenger.events({
    "submit .send - message": function(e) {
        e.preventDefault();
        var messageContent = e.target.querySelector("#message - input").value;
        if (messageContent) {
            Meteor.call("sendMessage", FlowRouter.getParam('contactId'), messageContent, function(error, result) {
                if (!error) {
                    e.target.querySelector("#message - input").value = "";
                }
            });
        }
    }
});
  1. server 目录的 methods.js 文件中添加发送消息的服务器方法:
Meteor.methods({
    sendMessage: function(contactId, content) {
        var sender = Meteor.user();
        Messages.insert({
            senderId: Meteor.userId(),
            senderName: sender.profile.name,
            receiverId: contactId,
            content: content,
            timestamp: new Date()
        });
    }
});
6. 应用的优化与测试

在完成基本功能开发后,我们需要对应用进行优化和测试,以确保应用的稳定性和性能。

优化方面
- 代码优化 :检查代码中是否存在冗余代码,对代码进行重构,提高代码的可读性和可维护性。例如,将一些重复使用的逻辑封装成函数。
- 性能优化 :对于数据查询和处理,尽量减少不必要的操作。例如,在获取联系人信息和消息时,使用合适的索引来提高查询速度。

测试方面
- 功能测试 :对应用的各个功能模块进行测试,确保登录、注册、个人资料填写、联系人显示、消息发送和接收等功能正常工作。
- 兼容性测试 :在不同的移动设备和浏览器上进行测试,确保应用在各种环境下都能正常显示和使用。可以使用模拟器和真机进行测试。

7. 总结与展望

通过以上步骤,我们成功开发了一个简单的移动信使应用。从最初的登录界面搭建,到个人资料界面、联系人界面和消息界面的实现,我们逐步构建了一个完整的应用。在开发过程中,我们利用了 MeteorJS 的强大功能,如路由管理、模板渲染和服务器方法调用,同时借助 Cordova 插件获取了移动设备的原生功能。

未来,我们可以对该应用进行进一步的扩展和优化。例如:
- 添加更多功能 :如群组聊天、消息通知、文件共享等功能,提升应用的实用性。
- 优化用户体验 :对界面进行美化,添加动画效果,提高用户的操作流畅性。
- 安全性提升 :加强用户身份验证和数据加密,确保用户信息和消息的安全。

以下是整个应用开发的流程图:

graph LR
    A[开始] --> B[登录界面开发]
    B --> C[个人资料界面开发]
    C --> D[联系人界面开发]
    D --> E[消息界面开发]
    E --> F[应用优化与测试]
    F --> G[应用完成]

通过这个流程图,我们可以清晰地看到整个应用开发的流程和步骤。希望这篇博客能为你开发移动应用提供有价值的参考。

开发过程关键步骤总结

步骤 操作内容
登录界面 添加相关包,创建目录和文件,设置路由和布局,添加 CSS 样式,自定义闪屏和图标
个人资料界面 添加路由,设置跟踪器进行重定向,创建布局和表单模板,添加服务器方法保存资料
联系人界面 添加路由,创建模板和辅助函数,安装 Cordova 插件读取联系人,添加服务器方法匹配联系人
消息界面 添加路由,创建模板和辅助函数,添加服务器方法发送消息
优化与测试 进行代码和性能优化,开展功能和兼容性测试
【无人机】基于改进粒子群算法的无人机路径规划研究[和遗传算法、粒子群算法进行比较](Matlab代码实现)内容概要:本文围绕基于改进粒子群算法的无人机路径规划展开研究,重点探讨了在复杂环境中利用改进粒子群算法(PSO)实现无人机三维路径规划的方法,并将其与遗传算法(GA)、标准粒子群算法等传统优化算法进行对比分析。研究内容涵盖路径规划的多目标优化、避障策略、航路点约束以及算法收敛性和寻优能力的评估,所有实验均通过Matlab代码实现,提供了完整的仿真验证流程。文章还提到了多种智能优化算法在无人机路径规划中的应用比较,突出了改进PSO在收敛速度和全局寻优方面的优势。; 适合人群:具备一定Matlab编程基础和优化算法知识的研究生、科研人员及从事无人机路径规划、智能优化算法研究的相关技术人员。; 使用场景及目标:①用于无人机在复杂地形或动态环境下的三维路径规划仿真研究;②比较不同智能优化算法(如PSO、GA、蚁群算法、RRT等)在路径规划中的性能差异;③为多目标优化问题提供算法选型和改进思路。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注算法的参数设置、适应度函数设计及路径约束处理方式,同时可参考文中提到的多种算法对比思路,拓展到其他智能优化算法的研究与改进中。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值