Android Framework 之HelloWorld(一)

        我用是友善之臂的NanoPC-T4开发板,CPU是瑞芯微rk3399,搭载android8.1版本,之后的实验都基于此平台。

开发板的wiki百科在http://wiki.friendlyarm.com/wiki/index.php/NanoPC-T4/zh,有兴趣的可以阅读一下。我不是打广告,我也是二手市场淘的,别人不要我便宜买了。

        这个Hellworld的最终功能是操控一个gpio管脚,控制外接led灯的亮和灭。

        理论上分三步:

1,实现一个按钮控件

2,利用JNI在控件的点击事件回调中调用so(linux的动态链接库)的接口

3,实现gpio的linux驱动(内核态),并在上述的so(用户态)中暴露出操作接口。

        现在先实现一个按钮控件。

下面比较详细记录项目创建过程,因为我自己也是新手,算是自用的笔记。

一、创建工程

Android Framework 之HelloWorld(一)_第1张图片

创建一个空的窗口:

Android Framework 之HelloWorld(一)_第2张图片

指定项目名称和目录,我这里的源码路径是com.mkelehk.helloworld,其实后面可以修改的,譬如将mkelehk改为demo文件夹:

Android Framework 之HelloWorld(一)_第3张图片

二、界面布局

按下“Finish”后,AS就自动为我们创建了一些源文件,譬如布局xml文件和java文件。我们可以通过修改xml文件来完成控件的布局,也可以拖动控件到“Design”视图里完成布局。右上角有个code-split-Design的选择,选择code的话只看xml文件,选择Design只看效果图,下图选择split:

Android Framework 之HelloWorld(一)_第4张图片

        我们可以用“Project”的模式来看工程文件,默认是以“Android”模式来展示源文件,在Project->app->res->layout->activity_main.xml(红框)就是布局xml文件了。默认有个“Hello world”的文本框。我们可以修改它,删掉一些位置信息,让文本框放在最上面:

Android Framework 之HelloWorld(一)_第5张图片

其中wrap_content是根据内容(文本)来适配宽高。修改文字为:“Used to control led lights!”,用来提示该app的功能。

        我们继续添加一个“按钮”,我们不采用拖控件的方式,而是直接修改xml,我发现AS在自动补全方面做得很好,譬如,输入“<”后就马上有各种控件的提示:

Android Framework 之HelloWorld(一)_第6张图片

        我们选择“Button”即可。

        选择完Button之后,AS又立马自动补全其他必须的一些字段,譬如,宽高等:

Android Framework 之HelloWorld(一)_第7张图片

按钮的宽我们选择“match_parent”,其中parent是外面的view框,也就是宽度扩展为跟view宽度一样:

Android Framework 之HelloWorld(一)_第8张图片

        但这样又覆盖掉之前弄好的文本框了,我们可以使用LinearLayout来进行布局,同时采用垂直方式分布:

Android Framework 之HelloWorld(一)_第9张图片

Android Framework 之HelloWorld(一)_第10张图片

Android Framework 之HelloWorld(一)_第11张图片

        这里有个问题,为什么我会知道orientation是用于垂直分布的呢,其实我们可以点击右上角的“Design”查看视图,右边栏有一列属性,可以供参考,英语好的应该一看就知道意思,像我英语差的,可以在“Design”上试着填写一些参数,看下视图有什么变化,然后“反标”回xml,看下xml是怎么写的,这样搞多了就知道这些属性怎么用了,熟能生巧:

Android Framework 之HelloWorld(一)_第12张图片

ok,至此已经完成界面的布局了。

三、实现具体业务

        按照前面的“大纲”,我们要实现按钮的点击回调事件。怎么写呢?

        虽然我不是搞安卓应用的,但以我的开发经验,一般拿到SDK后,第一件事肯定是“看文档”了!!

        安卓/QT都一样,我们有快捷键“Shift+F1”可以弹出帮助文档,因为当前还没有Java的Button类生成,我可以在activity_main.xml上找到“developer.android.com改为developer.android.google.cn,如https://developer.android.google.cn/reference/android/widget/Button.html

我们可到它有demo示例:

Android Framework 之HelloWorld(一)_第13张图片

        它提示说,要先在activity_main.xml布局文件里设定一个id,然后在java文件里注册回调函数,这里用到匿名函数,很方便,c++11也有。

        把代码添加进去后,发现“江山一片红”,没有加入相应的包,AS就是比较智能,它可以提示有多种解决方案供你选择:

Android Framework 之HelloWorld(一)_第14张图片

这样,选择“Import class”后,它自动帮你添加“import android.app.Activity;”,AS的自动补全方面很爽。异常代码块/if/else都可以自动添加譬如“Ctrl+Alt+T”,括号下(按Ctrl+shift+空格)能自动强制转换类型等等。

        button也能用上述提示的方法来自动添加包,也能通过阅读刚刚的帮助文档来获知应该包含什么包,譬如像下面的:

Android Framework 之HelloWorld(一)_第15张图片

        说真的,工作中代码的编写能力不如学会读懂文档和调试技巧,能快速定位问题。有些bug往往只是修改一两行代码,但排查起来可能是一天甚至更久。

        因为我们还没有实现C语言的so,所以先在回调函数里加个“吐司”,产生提示框用于调试。同时把按钮上的文字也修改一下,以实现这样的业务:

默认按钮显示“Led off”,当按下按钮,文本变为“Led on”,再按下提示“Led off”,同时产生“提示框”:

package com.mkelehk.helloworld;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private boolean isLedOn = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Button button = findViewById(R.id.Led);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // Code here executes on main thread after user presses button
                if(isLedOn == false) {
                    button.setText("Led off");
                    Toast.makeText(getApplicationContext(), "Led off", Toast.LENGTH_SHORT).show();
                }
                else {
                    button.setText("Led on");
                    Toast.makeText(getApplicationContext(), "Led on", Toast.LENGTH_SHORT).show();
                }

                isLedOn = !isLedOn;
            }
        });
    }
}

四、编译运行

        gradle配置不需要修改,使用默认的即可,或者将targetSdkVersion改为27也行,AndroidManifest.xml也暂时不用修改。

        这样我们就实现了一个按钮控件了,而且点击它会有反应。通过adb可以连接真机进行上机调试,下断点单步仿真也行。

        最后,如果开发APP过程中,文件目录结构改变了,譬如修改依赖包文件夹名字,它会导致R这个对象报错,除了需要修改java文件,import正确路径外,还要修改AndroidManifest.xml以及app/build.gradle下的applicationId字段,不然虽然能编译通过,但在真机运行中,logcat可能找不到那个进程名称,无法连接socket,也就没有log输出了:
package="com.example.helloworld">

defaultConfig {
        applicationId "com.example.helloworld"
        ...
 }

        根据文章开头的大纲,我们紧跟着就要使用JNI接口构建一个arm64平台的so动态库了。

 

你可能感兴趣的:(Android,Framework,android,studio4,framework)