Android实践小结

实践环境为:android-studio-bundle-162.4069837-windows(Android Studio 2.3.3 带 Android SDK 版)、该 Android Studio 自带的 JRE,系统环境为 Win10-1607。

前言

  由于上一届没有更新任何项目文档和学习文档,Shaun 只能自己去网上查找相关的资料,从零开始学习,顺便留下一些文档,正所谓:「代码未动,文档先行」,也算是实践出真知吧。

PS: 本次实践的项目主要来自 12.1Android 实战 :DrySister看妹子应用(第一版) — 项目搭建与简单实现http://www.runoob.com/w3cnote_genre/android) 以及目前手头上正在维护的项目。

布局篇

  首先打开 Android Studio ,新建项目,一路默认下去即可,等待片刻,“MainActivity.java” 文件的错误提示就会自然消失,将左侧栏上方的 “Android” 切换为 “Project”,打开 app -> src -> main -> res -> layout -> activity_main.xml,由于其默认是以 “Text” 的模式打开(Android Studio 右侧有个 “Preview” 标签可以进行当前布局预览),这对于小白来说不大好控制布局,所以需要在该文件底部将 “Text” 切换为 “Design”,如此可以进行拖拽式布局,以下正式开始进入 Android UI 的布局。至于具体如何进行布局设置,可以参考 Android ConstraintLayout 使用指南Android实现拖拽式布局开发----约束性布局 以下两篇资料。

  而若要使控件大小根据屏幕大小自适应,一般可使用相对布局,但如今的 Android Studio 默认新建的页面就是一种类似于相对布局的页面,所以直接在控件中设置 android:layout_width="match_parent" 以及 android:layout_height="match_parent" 属性即可,再设置 layout_margin 属性进行调整即可,而若要让控件大小随控件内的内容自适应,则只需要将 match_parent 更改为 wrap_content 即可。

编码篇

  首先新建自己的业务逻辑 java 代码,具体新建方法可参考 Android studio怎么创建一个Java类文件 ,在 MainActivity.java 文件所在目录上鼠标右键 New -> Java Class,新建完成之后即可编写自己的业务逻辑。若要新建文件夹,则在目录上鼠标右键 New -> Package 。若要使级联目录展开,例如 com.example.admin.myapplicationtest,则需要在该目录的父级目录新建一个 com.example.admin.test Package 即可将com.example.admin 目录展开。

页面跳转

  首先新建一个页面 jump_test_activity,在 \MyApplicationTest\app\src\main\res\layout,即 layout 文件夹上鼠标右键,“New” ==》“Activity” ==》“Empty Activity” (有多种 Activity 样式可供选择,Shaun 这里就以 Empty Activity为例了),随后弹出窗口,在 Activity Name 栏填写页面逻辑控制代码文件名 JumpTestActivity,在 Layout Name 栏填写页面 UI 设计代码文件名 jump_test_activity,在 Package name 以及页面逻辑控制代码文件所在在包名 com.example.admin.myapplicationtest.ui.activity,其它设置为默认即可,这样新建的页面的有个问题就是会有一个丑陋的标题栏,所以还需要去掉该标题栏,具体方法为:

  1. MyApplicationTest\app\src\main\res\values\styles.xml 文件中添加:

    1
    2
    3
    4
    <style name="AppTheme.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    </style>
  2. MyApplicationTest\app\src\main\AndroidManifest.xml 中的 <activity android:name=".ui.activity.JumpTestActivity"></activity> 更改为 <activity android:name=".ui.activity.JumpTestActivity" android:theme="@style/AppTheme.NoActionBar"></activity> ,再次编译运行即可看到标题栏已消失。

好了,准备阶段已经搞完,接下来就是正式的页面跳转了,一般页面跳转是用户点击事件发生的,所以需要添加一个具有点击事件的控件,一般而言就是 Button 了,这里设该 button 的 id 为 page_jump_btn;该 button 所在页面为 MyApplicationTest\app\src\main\res\layout\activity_main.xml,则在对应的逻辑控制文件MyApplicationTest\app\src\main\java\com\example\admin\myapplicationtest\ui\activity\MainActivity.java 中的页面跳转代码为:

1
2
3
4
5
6
7
8
page_jump_btn = (Button) findViewById(R.id.page_jump_btn);
page_jump_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, JumpTestActivity.class);
MainActivity.this.startActivity(intent);
}
});

如此,在主界面中点击跳转按钮,即可跳转到新建页面。

URL 中的坑

  在学 12.2 的时候,由于请求的URL地址中有中文“福利”,所以其返回的字符串为:

1
2
3
4
{
"error": false,
"results": []
}

可以看到 “results” 的值为空,这显然是错的,后面调试发现需要对 URL 地址转义(这都 8102 年了,为什么 URL 地址中还要有中文,或者说为什么 URL 地址还不支持解析中文 ╮(╯▽╰)╭),具体转义代码如下:

1
2
3
fetch_url = Uri.encode(fetch_url);  // 将URL地址转义
fetch_url = fetch_url.replace("%3A", ":"); // 将%3A替换为:
fetch_url = fetch_url.replace("%2F", "/"); // 将%2F替换为/

主要参考资料为:Android url中文乱码问题及解决办法Android URL encode 空格处理

SQL 语句中的坑

  在使用字符串拼写 SQL 语句时,一定要注意 SQL 语句中的空格,要不然拼起来的 SQL 语句可能语法不通而导致 APP 崩溃。如在使用创建表的 SQL 语句时,可能的错误写法(不注意空格)如下:

1
2
3
4
5
6
7
8
9
10
11
12
String create_table_sql = "CREATE TABLE IF NOT EXISTS" + TableDefine.TABLE_FULI + "("
+ TableDefine.COLUMN_ID + "INTEGER PRIMARY KEY AUTOINCREMENT,"
+ TableDefine.COLUMN_FULI_ID + "TEXT,"
+ TableDefine.COLUMN_FULI_CREATEAT + "TEXT,"
+ TableDefine.COLUMN_FULI_DESC + "TEXT,"
+ TableDefine.COLUMN_FULI_PUBLISHEDAT + "TEXT,"
+ TableDefine.COLUMN_FULI_SOURCE + "TEXT,"
+ TableDefine.COLUMN_FULI_TYPE + "TEXT,"
+ TableDefine.COLUMN_FULI_URL + "TEXT,"
+ TableDefine.COLUMN_FULI_USED + "BOOLEAN,"
+ TableDefine.COLUMN_FULI_WHO + "TEXT"
+ ")";

以上写法无法正确建表,甚至会因为错误 SQL 语句而导致 APP 闪退,正确的写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
String create_table_sql = "CREATE TABLE IF NOT EXISTS " + TableDefine.TABLE_FULI + " ("
+ TableDefine.COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ TableDefine.COLUMN_FULI_ID + " TEXT, "
+ TableDefine.COLUMN_FULI_CREATEAT + " TEXT, "
+ TableDefine.COLUMN_FULI_DESC + " TEXT, "
+ TableDefine.COLUMN_FULI_PUBLISHEDAT + " TEXT, "
+ TableDefine.COLUMN_FULI_SOURCE + " TEXT, "
+ TableDefine.COLUMN_FULI_TYPE + " TEXT, "
+ TableDefine.COLUMN_FULI_URL + " TEXT, "
+ TableDefine.COLUMN_FULI_USED + " BOOLEAN, "
+ TableDefine.COLUMN_FULI_WHO + " TEXT"
+ ")";

调试篇

  编码完成之后,一般而言需要进行调试,Android Studio 的调试可参考 【Android 开发入门】android studio 控制台打印输出日志 ,进入调试模式具体方法为:点击上方工具栏中的 Debug 'app' 图标,而不是直接 Run 'app',进入调试模式之后,点击下方的 “Android Monitor”,切换到 “logcat” 标签,即可查看调试信息。

  华为手机打印调试信息可参考 华为手机logcat不出日志解决方案。这里由于 Shaun 还没有对 AndroidManifest.xml 进行修改,所以该 APP 在点击 Button 的时候会直接闪退,调试窗口出现 java.lang.SecurityException: Permission denied (missing INTERNET permission?) 错误信息,参考 android菜瓜笔记之missing INTERNET permissionSecurityException: Permission denied (missing INTERNET permission?) 可知,该 APP 没有网络权限,所以需要在 AndroidManifest.xml 中添加网络权限,具体在 manifest 标签中添加语句 <uses-permission android:name="android.permission.INTERNET" />,如此该 APP 就能正常执行了。

PS: 如果是对应用发生闪退或崩溃的原因进行调试,建议直接在 logcat 中搜索 fatal 关键字

附录

更换马甲重新发布为另一个 app

  即一样的代码却编译出另一个相同的 app,在某些特殊的需求(使两个功能大致一样的 app 共存在一台手机上)上可能需要这个技巧,具体步骤如下(以 MyApplicationTest 更名为 MyApplication 为例):

  1. 首先将 MyApplicationTest 文件夹(即 APP 根目录)更名为 MyApplication;(这一步不是刚需)
  2. MyApplicationTest\app\src\main\res\values\strings.xml 文件中 <string name="app_name">MyApplicationTest</string> 更改为 <string name="app_name">MyApplication</string>
  3. MyApplicationTest\app\build.gradle 文件中 applicationId "com.example.admin.myapplicationtest" 更改为 applicationId "com.example.admin.myapplication" 。(这一步是刚需)

如此,即可另外安装一个全新 APP,同时保留原有 APP,至于 applicationId 的更多作用和用法可参考 设置应用 ID 。更换 APP 图标只需在 app 文件上鼠标右键, “New” ==》“Image Asset” ,即可弹出设置 app 图标窗口,或者直接更改 AndroidMainfest.xml 文件中的 android:icon 也可。

后记

  排版可能有点乱,毕竟是随便写的,碰到问题就简单的记录一下,Shaun 这次的实践过程可在 AndroidLearning 中查看,页面跳转的方法来自手头上正在开发维护的一个项目,附录中第一个问题的来源是对方提出的一个特殊需求。