“多年以前,我构建了自认为是有史以来销量最高的黑莓应用:BBSmart Email Viewer。今年我35岁,那款应用也已经过去了很多年,现在是时候谈一谈我是如何实现的了!我将BBSmart Email Viewer的源代码放在了GitHub上,还有我作为独立黑莓应用开发者时构建的其他应用。”

声明:本文已获作者Neil Sainsbury翻译授权。

作者 | Neil Sainsbury

译者 | 弯月,责编 | 郭芮

头图 | CSDN 下载自视觉中国

出品 | CSDN(ID:CSDNnews)

以下为译文:

多年以前,我构建了自认为是有史以来销量最高的黑莓应用:BBSmart Email Viewer。这样说有点奇怪,而且这只是在曾经存在过的黑莓应用开发者的小众社区之内,在这个社区外的反响说实话我并不清楚。但是这个应用给我的人生带来了巨大的影响。关于这一点尽管我有很多话可以讲,但是有一点是我一直以来都想写出来的,那就是这个应用使用了一个很少有人能想到的技巧。

今年我35岁,那款应用也已经过去了很多年,现在是时候谈一谈了!我对BBSmart早已失去了商业兴趣,所以我将BBSmart Email Viewer的源代码放在了GitHub上,还有我在自己的公司BBSmart作为独立黑莓应用开发者时构建的其他应用(其中许多应用也都非常成功,只是没有BBSmart Email Viewer那样成功而已)。如果你愿意看一看,请不要对我的代码太苛刻,毕竟那只是刚开始学编程的23岁程序员的作品而已:)

BBSmart Email Viewer是什么?

BBSmart Email Viewer是一款黑莓的邮件客户端。尽管众所周知黑莓以邮件服务为中心,但原生的邮件应用有很多欠考虑的地方,特别是在渲染HTML邮件的方面——它无法正确渲染HTML邮件,会显示很多乱七八糟的HTML标签。BBSmart Email Viewer有很多很酷的附加功能(回复模板、便签、任务和日历集成等),但最主要的卖点是它能正确渲染HTML邮件。

尽管BBSmart Email Viewer只是一个第三方邮件客户端,但它能够无缝地替换原生客户端,拥有原生客户端的一切功能。这貌似不太可能,不仅是因为黑莓没有提供实现邮件客户端所需的绝大多数核心功能的API,而且像今天的安卓那样允许开发者替换核心应用的API也没有。

那么,我是怎样实现的呢?

史上销量最高的?

没错!至少我这样认为。当时的移动环境与今天有很大区别。当时安卓和iPhone都还没有出现。黑莓上也没有原生的“应用程序商店”,人们只能去类似于MobiHand、Handango和CrackBerry之类的网站上购买应用程序,或者使用运营商预装的商店书签(如AT&T、T-Mobile等)。由于销售非常碎片化,所以很难得出确切的答案。

但是,我有理由相信这个应用程序是有史以来销量最高的黑莓应用。

BBSmart Email Viewer发布于2007年,一经发布就占据了所有销量排行榜的第一名。这个应用受到了多家媒体的报道,评论的赞美不绝于耳,我也接受了很多采访。但是这个应用程序的独特之处在于,它占据了各大主要网站的销量最佳排行榜的第一名长达一两年之久(我没有精确统计)。一年多的时间里,BBSmart Email Viewer一直是销量最高的黑莓应用。这个应用在企业里也卖出了很多,包括几万分授权,还有一份与美国的运营商签订的批量部署合约。

由于这些销量,我对黑莓开发者的行业非常熟悉,也熟悉了这个行业的所有知名人物。在BBSmart的事情沉淀之后,我加入了黑莓,作为开发者关系团队的一员,之后成了黑莓的开发者关系团队的总监。我听到的、看到的一切都表明,BBSmart Email Viewer的销量超过了其他一切应用。

成就一切的魔法#1

那么,为什么BBSmart Email Viewer能够无缝替换原生邮件客户端呢?有一天,我在浏览黑莓API文档时发现了一个很有意思的东西:你可以注册一个监听器,监视用户在原生邮件客户端中打开一封邮件的行为。BBSmart Email Viewer会在一开始就注册监听器:

Session.addViewListener(this);

当用户打开邮件时,该监听器就会被触发,调用其open处理函数。从这个处理函数里竟然能够获得当前UI栈的引用,只需调用UiApplcation.getUiApplication()即可。有了这个引用,就可以对当前显示栈中的任何画面做任何事情。你可以从当前栈中移除画面,加入新的画面,也可以深入修改任何画面中的任何UI组件(删除、替换等等)。

这一点非常危险,也非常强大。因为从任何全局的事件处理函数中都可以做到这一点,所以在黑莓上可以创建一个应用,随时替换或更改任何正在运行的应用程序的任何部分。例如,理论上甚至可以注册一个频繁触发的全局事件处理函数,时刻唤醒并检查“HSBC Bank”这个应用是否在运行,如果在运行且用户位于转账画面,则更改“收款银行账号”中的值……

(旁注:后来我用这个时刻唤醒功能构建了BBSmart Alarms Pro——一个支持多个闹钟的应用。注册RealtimeClockListener就可以以分钟的精度唤醒。)

不论如何,对于我来说,我需要做的就是获得底层打开邮件的事件(由原始的打开邮件事件发送),格式化,然后在显示栈上放一个全新的界面,原生的邮件界面依然在后台运行,但被新的界面完全遮住。

UiApplication.getUiApplication().pushScreen(new EmailViewScreen(m, formatter));

当然,在显示邮件时我也做了许多工作来清理邮件内容,最后在一个HTMLField里显示邮件内容。

当用户关闭邮件后,我会同时移除我自己的界面和原生的邮件界面,所以从用户的角度来看,看起来就像是原生邮件界面从来没有启动过一样:

private void exitToMessageList() {// Close this and the previously opened// email view screenUiApplication.getUiApplication().popScreen(UiApplication.getUiApplication().getActiveScreen());UiApplication.getUiApplication().popScreen(UiApplication.getUiApplication().getActiveScreen());
}public boolean onClose() {if (this.getScreenBelow() == mailScreen) {exitToMessageList();} else {close();}return true;
}

成就一切的魔法#2

在完成这些工作后,我就可以显示自己的邮件界面(而不是显示原生的邮件界面)。但仍有一个问题:怎样才能在没有API支持的情况下实现所有原生客户端的功能,如打开邮件附件、回复、跳到下一封或前一封未读邮件等?

关键的一点是黑莓的菜单。如果你不熟悉黑莓,那我来介绍一下:黑莓上有一个独立的物理菜单键,按下后可以弹出“应用程序内菜单”,其中显示所有全局和上下文相关(取决于当前的活跃点)的菜单项。

当然,原生邮件应用已经包含了所有原生的邮件菜单选项。所以我同样使用了前面得到的原生画面的引用,当用户在BBSmart Email Viewer里选择“Reply”,我就会获得原生画面的引用,根据该引用获得原生画面的菜单,最后“调用”相应的菜单项。例如,下面是BBSmart EmailViewer中的“Reply”菜单项的定义:

private MenuItem replyMenuItem = new MenuItem(replyMenuItemText, 0, 0) {public void run() {findDefaultMenuItem("Reply").run();if (UiApplication.getUiApplication().getActiveScreen().getScreenBelow() != mailScreen) {close();}}
};

其中findDefaultMenuItem和mailScreenMenu的定义为:

private MenuItem findDefaultMenuItem(String name) {final int M_SIZE = mailScreenMenu.getSize();MenuItem item;for (int i = 0; i < M_SIZE; i++) {item = mailScreenMenu.getItem(i);if (item.toString().equals(name)) {return item;}}return null;
}
mailScreen = UiApplication.getUiApplication().getActiveScreen();
mailScreenMenu = mailScreen.getMenu(0);

仔细管理原生邮件菜单,BBSmart Email Viewer就可以提供原生邮件应用中的所有功能。

然后……

许多开发者想不明白BBSmart Email Viewer的工作原理——曾经每隔几周我就会收到一封邮件询问应用的原理,当然,我没有告诉过任何人。尽管如此,一些其他的开发者最后也发现了这个技巧,所以最终我的应用还是有人复制出来了(外观和功能几乎全盘复制)。但是一个应用要真正在商业上取得成功,你还需要大量的努力,不断的通宵,不断更新,做各种市场营销活动,处理客户交流,商业关系,以及一切必须的事情。

不论如何,我依然认为,这个看似愚蠢的小技巧改变了我的人生。

原文:https://www.neilwithdata.com/how-i-built-bbsmart

【End】

推荐阅读 

☞75.58 亿美元成交!美国最大规模 5G 毫米波频谱拍卖

☞不用掉一根头发!用 Flutter + Dart 快速构建一款绝美移动 App

☞超轻量级中文OCR,支持竖排文字识别、ncnn推理,总模型仅17M

☞和黑客斗争的 6 天!

☞一文了解 Spring Boot 服务监控,健康检查,线程信息,JVM堆信息,指标收集,运行情况监控!

☞用 3 个“鸽子”,告诉你闪电网络是怎样改变加密消息传递方式的!

你点的每一个在看,我认真当成了喜欢

畅销款黑莓应用是怎样构建的?相关推荐

  1. 回归架构本真:从规划、思维到设计,构建坚不可摧的架构根基

    关于什么是架构,业界从来没有一个统一的定义.Martin Fowler在<企业应用架构模式>中也没有对其给出定义,只是提到能够统一的内容有两点: 最高层次的系统分解: 系统中不易改变的决定 ...

  2. 黑莓手机时代落幕;阿里巴巴为 Linux 内核调度器提出新概念;清理 Linux 内核“依赖地狱” | 开源日报

    整理 | 宋彤彤 责编 | 屠敏 开源吞噬世界的趋势下,借助开源软件,基于开源协议,任何人都可以得到项目的源代码,加以学习.修改,甚至是重新分发.关注「开源日报」,一文速览国内外今日的开源大事件吧! ...

  3. 黑莓管理器6.0_BlackBerry Java SDK 7.0 Beta发布

    黑莓管理器6.0 BlackBerry Java SDK 7.0 Beta发布 BlackBerry Java SDK 7.0版的测试版现已发布. 该SDK包括用于BlackBerry Bold 99 ...

  4. 中科创达成为黑莓 Jarvi 官方认证合作伙伴

    近日,黑莓(BlackBerry)公布了旗下产品Jarvis 2.0在亚太地区的13家官方认证合作伙伴,中科创达位列其中,并将与黑莓携手共同推进Jarvis在亚太地区的部署,帮助用户及时发现软件中的安 ...

  5. 鸿蒙os黑莓,王员外:微软、黑莓都失败了,华为依靠鸿蒙OS,很难超过联想

    众所周知谷歌从去年5月开始停止授权GMS服务,华为手机销量极速下跌,有国外消费者通过了一些手机助手,让华为手机重新安装GMS,进而继续使用谷歌Paly.不过后来被谷歌发现,直接把华为手机认证全部取消, ...

  6. 强强联手 | 博泰车联网与黑莓达成战略合作

    2022年1月5日,博泰车联网与黑莓有限公司达成战略合作:利用博泰车联网座舱集成核心技术及黑莓QNX®技术优势,将黑莓IVY™集成至博泰智能数字座舱,提供面向服务的架构 (SOA) 解决方案,开发数据 ...

  7. 在k8s中使用gradle构建java web项目镜像Dockerfile

    在k8s中使用gradle构建java web项目镜像Dockerfile FROM gradle:6-jdk8 AS build COPY --chown=gradle:gradle . /home ...

  8. JAVA用最简单的方法来构建一个高可用的服务端,提升系统可用性

    一.什么是提升系统的高可用性 JAVA服务端,顾名思义就是23体验网为用户提供服务的.停工时间,就是不能向用户提供服务的时间.高可用,就是系统具有高度可用性,尽量减少停工时间.如何用最简单的方法来搭建 ...

  9. 通过前序遍历和中序遍历构建二叉树 python实现

    前言 通过前序遍历和中序遍历构建二叉树的原理,主要是找前序遍历根节点在中序遍历中的位置,然后将二叉树而成左子树和右子树,然后依次进行这样的操作,思路还是比较简单的 代码 class Node:def ...

最新文章

  1. 详解基于busybox、dropbear、ngnix制作完整的嵌入式Linux系统
  2. halcon知识:hough变换检出图像的直线
  3. Light-Head R-CNN相关资料
  4. Coverage analysis in ABAP in Eclipse
  5. 一道无限级分类题的 PHP 实现
  6. maven netty 配置_进阿里、腾讯、字节跳动、美团必掌握的Netty
  7. 华为交换机端口不配置access_华为交换机如何配置端口组?华为交换机端口组-百度经验...
  8. IntentService用法小结
  9. CCF201609-2 火车购票(100分)
  10. 分蛋糕问题 —— 9 个烧饼分给 10 个人
  11. java判断字符串是否是空格_检查字符串在Java中是否为空格,空(“”)或null
  12. stm32程序跑飞_mm32芯片使用心得(三)音频播放程序修改
  13. grid lightbox gallery
  14. 系统辨识(六):最小二乘法的修正算法
  15. Laya1.x Timer小记
  16. JavaWeb项目部署服务器并配置ssl证书教程
  17. PS制作各种证件照及换背景色
  18. Python协议攻击脚本(一): Scapy的使用
  19. Arcgis加载shp文件
  20. python 基础代谢率计算_计算基础代谢率(BMR)

热门文章

  1. chrome里面模拟手机上打开网页的场景方法
  2. 解析xlsx与xls--使用2012poi.jar
  3. matlab 手工实现normalize函数 未定义与 ‘double‘ 类型的输入参数相对应的函数 ‘normalize‘
  4. 苹果手机软件升级密码_拥有苹果全家桶以后那些事
  5. opencv 编译安装时出现报错 modules/videoio/src/cap_ffmpeg_impl.hpp:585:34: error: ‘AVStream {aka struct AVStre
  6. 中国农用喷洒机行业市场供需与战略研究报告
  7. 金属拉链滑块行业调研报告 - 市场现状分析与发展前景预测
  8. 中国晶体谐振器行业市场供需与战略研究报告
  9. 2021-2025年中国顶级服务行业市场供需与战略研究报告
  10. r语言岭回归参数选择_78-预测分析-R语言实现-岭回归与LASSO回归