Hi there 👋

Welcome to my blog

Android[2] - Playing Music when Receiving Custom Broadcast

当收到自定义广播时播放音乐 想要在收到广播的时候播放音乐,大体分为两个步骤。首先要接收到广播,然后通过服务播放音乐。 01 广播 Android 应用与 Android 系统和其他 Android 应用之间可以相互收发广播消息,这与发布-订阅设计模式相似。这些广播会在所关注的事件发生时发送。举例来说,Android 系统会在发生各种系统事件时发送广播,例如系统启动或设备开始充电时。再比如,应用可以发送自定义广播来通知其他应用它们可能感兴趣的事件(例如,一些新数据已下载)。 接收广播有两种方式,一种是使用静态文件注册广播接收器、另外一种是动态的注册广播接收器。此处我们将分别使用两种方法介绍如何接收系统广播和自定义广播。 系统广播 我们将使用静态注册广播接收器的方式来接收接收短信产生的系统广播。 再Manifests.xml文件中声明Receiver <receiver android:name=".SmsReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> 创建 BroadcastReceiver 子类并实现 onReceive(Context, Intent) package xyz.retrove.androidcrouse2; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class SmsReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent serviceIntent = new Intent(context, MyService.class); //在广播组件里,通过上下文对象启动音乐播放服务组件 context.startService(serviceIntent); //新建调用Activity组件的意图 Intent activityIntent = new Intent(context, MainActivity....

May 11, 2021 · 2 min · Retrove

Android[1] - Wechat Like Interface Design

Android 类微信界面设计 设计APP门户界面,其中包含4个tab切换效果。 01 功能分析 微信的界面非常的简单(如图所示),顶端是一个操作栏,上面有此APP的名字以及一个加号按钮,点击加号按钮后会出现一个下拉菜单展示所有可执行的快捷操作。底部是一个导航菜单,点击四个不同的按钮,屏幕中间的内容会跟随其一同变化。 因此,我们大致的思路是:页面应该包含一个TopAppBar,一个ButtomNavigationMenu以及四个Fragment。 为了与Android的官方风格保持一致,这里我们使用 Android Material Design 控件进行开发,最后的效果应该如下图所示。 02 代码实现 首先,我们需要在activity_main.xml中添加TopAppBar和ButtomNavigationMenu两个控件以及中间显示内容的Fragment,并且为他们添加合适的约束条件。 需要注意的是,这里的Fragment由于需要动态填充,需要使用FragmentContainerView并且不要指定fragment的name。 <?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" android:orientation="vertical" tools:context=".MainActivity"> <com.google.android.material.appbar.AppBarLayout android:id="@+id/appBarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/topAppBar" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/Widget.MaterialComponents.Toolbar.Primary" app:menu="@menu/top_app_bar" app:navigationIcon="@drawable/ic_android_black_24dp" app:title="@string/page_title" /> </com.google.android.material.appbar.AppBarLayout> <androidx.fragment.app.FragmentContainerView android:id="@+id/content" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintBottom_toTopOf="@+id/bottom_navigation" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/appBarLayout" /> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottom_navigation" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:menu="@menu/bottom_navigation_menu" /> </androidx.constraintlayout.widget.ConstraintLayout> TopAppBar 由于在activity_main.xml当中我们指定了顶部的应用栏的菜单为@menu/top_app_bar,我们需要在menu文件夹下创建一个名为top_app_bar的菜单文件。 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas....

April 5, 2021 · 1 min · Retrove

Simple Factory Pattern

设计模式 - 简单工厂模式 综述 Overall 简单来说,简单工厂模式是由一个工厂类来创建其他类的实例。根据传入工厂类参数的不同,工厂类可以生成不同类的对象(通常这些类都继承自同样的父类)。 值得注意的是,简单工厂模式并不是一个成熟且规范的设计模式,因为他违背了软件设计的开闭原则(即每次增加新的产品都需要修改工厂类的逻辑判断)。 实例 Example 用户去超市购物,可以选择多种支付方式,包括现金、信用卡、微信、支付宝。请按照简单工厂模式的思想设计一个程序,让超市收银方类(Client)知道用户是使用的什么支付方式,支付了多少钱。 请画出对应的类图,并编写代码。 类图 Class Diagram 具体代码 Code 工厂类 public class PaymentFactory { public static Payment selectPayment(String paymentType) throws Exception { if(paymentType.equalsIgnoreCase("wechat")){ return new WechatPayment(); } else if (paymentType.equalsIgnoreCase("alipay")){ return new AlipayPayment(); } else if (paymentType.equalsIgnoreCase("cash")){ return new CashPayment(); } else if (paymentType.equalsIgnoreCase("creditcard")){ return new CreditCardPayment(); } else{ throw new Exception("暂不支持该支付方式"); } } } 抽象支付类 public interface Payment { public void pay(int amount); } 微信支付类...

March 29, 2021 · 1 min · Retrove

Git Commit Norm

Git 提交规范 在Git的整个流程中,commit作为一个必经之路,要求每次都必须说明这次提交的内容。但据我观察,长时间以来大部分程序员对此并不上心,经常出现不知所云的Commit message(类似:http://www.commitlogsfromlastnight.com/)。 为了避免这种糟糕的Commit message,是时候引入一个新的规范了(并不新。 01 作用 采用这种规范还有以下的好处: 通过脚本生成CHANGELOG.md 在Angular规范中,他们使用了new features, bug fixes, breaking changes三个部分作为changlog的骨架。这一点可以作为参考。 在git bisect时过滤不重要的commit 小的格式更改(加几个空格、空行,改一下缩进,加几句注释等等)可以被直接过滤掉。 治愈你幼小的♥ 02 格式 Commit message包括三个部分:Header、Body和Footer。 <type>(<scope>): <subject> <BLANK LINE> <body> <BLANK LINE> <footer> 其中,header 是必需的,body 和 footer 可以省略。 不管是哪一个部分,任何一行都不得超过72个字符(或100个字符)。这是为了避免自动换行影响美观。 特殊情况: 如果这一次提交的内容时回滚到了之前某一次的提交,它的格式会有所不同(如下)。 revert:[回滚到那个版本的header] This reverts commit <hash> 此处hash为被撤销 commit 的 SHA 标识符。 2.1 Header Header部分只有一行,包括三个字段:type(必需)、scope(可选)和subject(必需)。 其中,type说明commit的类别: feat:新功能(feature) fix:修补bug docs:文档(documentation) style: 格式(不影响代码运行的变动) refactor:重构(即不是新增功能,也不是修改bug的代码变动) test:增加测试 chore:构建过程或辅助工具的变动 如果type为feat和fix,则该 commit 将肯定出现在 Change log 之中。其他情况(docs、chore、style、refactor、test)由你决定,要不要放入 Change log,建议是不要。...

February 28, 2021 · 1 min · Me

Hello World!

从Wordpress到Gridea再到最后的Hugo,这个个人博客总算是有了它最终的归宿。作为一名程序员,新博客的第一篇就简单的总结以下Hugo的搭建流程,以及静态博客生成器相较于动态博客的优点。 搭建一个静态博客 静态博客的搭建由于不需要数据库等服务端的配置,相较于动态博客来说简单不少,仅仅需要将生成器的环境在本地搭建好,再准备好博客的内容就万事大吉了。下面我将用Hugo + GitHub Pages进行举例。 01 开始! 万事开头难,然而开头也不难,第一步需要下载Hugo最新的release。 前往https://github.com/gohugoio/hugo/releases下载最新的Hugo Release。对于MacOS、Linux来说可以直接使用homebrew等工具直接安装,安装过程和windows略有不同,具体请参考官方文档https://gohugo.io/getting-started/quick-start/。 解压后打开命令行终端,进入安装目录。 输入hugo.exe version查看是否能正常启动。(此处可以将Hugo添加到环境变量,便于后续指令的输入。为了书写上简化,后续用hugo代替hugo可执行文件的路径。) 此时如果能够正常显示版本,说明你的Hugo在本地已经安装好了。 02 准备GitHub Page仓库 相比动态博客需要单独租用VPS或者服务器来说,静态博客在经济上更让人省心。由于不需要后台,我们可以直接将博客托管在GitHub Page、Dropbox等存储服务提供商上。这里我们用GitHub进行演示: 新建一个名为[你的GitHub用户名].github.io的仓库 进入仓库的setting 仓库Setting 将下方的Source更改为/docs 调整Source 此处也可以不调整至/docs,如果调整的话后续部署时需要将输出目录从/public改为/docs,如果不调整的话后续仅需要上传/public即可。 至此你的GitHub Pages也配置好了。 03 建站 输入hugo new site [你的站点名字]创建一个新的站点。...

February 28, 2021 · 1 min · Me