从零开始用Andrid Studio开发一个简单的垃圾分类查询APP(2)

系列目录

从零开始用Andrid Studio开发一个简单的垃圾分类查询APP(1)
从零开始用Andrid Studio开发一个简单的垃圾分类查询APP(2)
从零开始用Andrid Studio开发一个简单的垃圾分类查询APP(3)
从零开始用Andrid Studio开发一个简单的垃圾分类查询APP(4)-完结篇

正文

时隔几天了,我终于回来更新了,(没有想好什么理由那就只能“啊哈哈”一下了)

书接上回

上回书说到,我们在首页通过新建并引用布局文件添加了一个顶部导航栏,并在上面随便放了两个按钮。

回到现在

那么接下来我们该做什么呢?
当然是继续做首页的布局啦,距离我们目标首页,还差一张图,一个输入框,一个搜索按钮,以及一个引用句子。
那么现在就开始插入图片吧。

1.首页布局

插入图片很简单,在activity_main.xml文件中写一个ImageView就可以了,

<ImageView
        android:id="@+id/main_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/protectenvironment"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/include" />

接下来是添加搜索用的单行输入框和搜索按钮,
这里用一个EditText和一个Button来实现,很简单,不过楼主这之前发现了一个很有意思的东西,ConstraintLayout库,我们一般的AS的可视化操作很拉胯,基本什么都做不到,但是有了这个,我们可以直接用可视化工具来放控件了,说着楼主就试了试。
具体和这个库相关的可以移步看下面这个链接:

Android新特性介绍,ConstraintLayout完全解析

关于如何引入依赖的问题,楼主试了很多次,发现在build.gradle文件里直接输入几乎没有成功过(可能是楼主确实手残),和楼主一样的朋友们,大家可以在 “ File-Project Structure“ 中的 Dependencies 的中间
在这里插入图片描述
点击这个加号按钮,然后在搜索框中输入库名,注意:一定要输入尽可能完整地名字!
这个搜索系统很怪,楼主以前有次用这个搜索,只输入关键词,结果根本找不到,直到后面输入了全名,打开了新世界的大门。
找到之后哦双击就可以导入了,AS会自动下载引用这个库。
完成之后,我们就可以直接切换成Design模式,然后拖控件和控制缩放了(当然,控件的动作还是要用代码的啦)(这里把能拖的边都拖一拖,不然会有提示报错,不过这个错没什么影响)
在这里插入图片描述
最后再拖入一个textview,我们首页的初步布局就做好了。

在连接api前,我发现一个问题:我们首页要什么返回啊歪?
所以我把返回删了,另外删了之后,我发现之前的LinourLayout线性布局就不行了,我们的“补充”按钮会自己跑到前面,除非我留着一个文本框把它怼在后面,所以我把title改成了RelativeLayout,
改后代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="60dp"
    android:background="@drawable/title_bg">


    <Button
        android:id="@+id/title_add"
        android:layout_width="108dp"
        android:layout_height="55dp"
        android:layout_gravity="center"
        android:layout_marginStart="298dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="5dp"
        android:layout_marginEnd="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginBottom="5dp"
        android:background="@drawable/add_bg"
        android:text="我有补充"
        android:textColor="#fff" />

</RelativeLayout>

用margin来控制button的位置,很怪(大概有问题),不过能成功就行了。

2.连接API

好了,回到正题,如何连接API呢?
好了,这是一个大问题,我不会了(菜鸡的我)。
还是继续查吧~
课本上的API导入示例是百度地图的API,看了一下,发现和我们要用的天行数据API用法差距好大,至少天行数据没有提供给我们什么专用的sdk,好了,课本没用了(丢)。

经过楼主半个多小时的查询,最终还是没有查到什么详细的答案
(此贴完结,楼主已跳楼)(误)
但是,天无绝人之路,感谢这位大佬的博客

基于Android实现自带谷歌语音识别垃圾分类APP

以及附带的源码,让我重新看到了希望。
话不多说,这就下载下来看看大佬是怎么导入API的。

导入大佬的APP看一下,
在这里插入图片描述
好家伙,还要重新下gradle,我哭了。还记得当时刚装这个的时候,额,我好像没遇到问题。
还记得刚开始帮朋友装AS的时候,他的gradle一直下载不了,不管怎么改。

这个下载的好慢,但是真的不敢动

2S.所以在下载的时候,我们再来梳理一下现在的思路:

我们现在完成了两个xml,分别是一个导航栏的,一个是首页布局的。
首页的布局我们已经完成了,其中“补充”按钮我们打算通向一个单独的页面,其中可以输入“垃圾名称”、“垃圾描述”、“垃圾分类”的内容,并包含一个按钮用来把信息放入数据库,还有一个按钮用来返回。完成后,会在页面下方出现完成的小提示。
“搜索”按钮用于向网页API发送数据,并返回到一个新的结果页面,结果页面可以把返回结果按列表排列,列表上显示“名称”、“分类”,进一步点开显示“名称”、“分类”、“分类解释”、“包含信息”、“小提示”,至于为什么这么多,因为它返回的信息就这么多。另外这两个页面也都需要有返回按钮,但不需要发布按钮。
“美句”模块导入api后,还需要一个计时器,比如每隔多久自动发送一次数据换一个句子,做不到的话就切换页面换个句子也行。
暂定的页面就这么多,也就是还需要4个页面包含单独的布局和活动及一个包含返回的导航栏。

额,好吧,下载完gradle好像也没什么用,没有办法打开,看了一下是因为什么东西只适配我现在的6.1.1版本,所以我在弹出的窗口改成了6.1.1,结果就成了,试了下,可以打开大佬的app了。(为了测试我还专门给模拟器里装了一个搜狗)

package aclass.com.example.garbgeapp.Untils;

import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;

public class OkhttpUntils {//封装的网络访问的代码
    public static void  OkHttpPost(String url, String json, Callback callback){//这个是post方法访问数据,这里没有使用,不需要管
        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(MediaType.parse("application/json;charset=utf-8"),json);
        Request request = new Request.Builder().url(url).post(body).build();
        client.newCall(request).enqueue(callback);
    }
    public static void OkHttpGet(String url, Callback callback){//这里APP访问采用的是get获取数据的方法,向网络发送请求
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        client.newCall(request).enqueue(callback);
    }
}

从上面的代码中可以看出,大佬用了一个Okhttp包,关于get和post两种请求方式,我这里就不赘述了,我大概的理解就是get传数据少而且不安全,post可以传大文件且较安全一点,但是get更方便,直接挂在url后面就可以了。
那~我们这个肯定就用get方法了。
我在java文件夹下创建了一个For_API的文件夹用于专门放和api相关的文件,然后新建了一个java class用于封装get方法。
不过在这之前,我们还需要下载一个Okhttp的jar包,这个包网上随便就能找到离线包,(CSDN已经有了,我也上传不了,所以大家自己找找吧)

package For_API;

        import okhttp3.Callback;
        import okhttp3.OkHttpClient;
        import okhttp3.Request;

public class Okhttp_work {
    public static void OkHttpGet(String url, Callback callback){
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        client.newCall(request).enqueue(callback);
    }
}

封装完成后,下一步就是操作首页了,先依次声明一下我们的控件,

	private EditText text_search_garbage;
    private Button btn_add_garbage,btn_search_garbage;
    private TextView tv_beauty;

接下来我们用美句来学习怎么调用网页API,
首先定义两个字符串用来放我们的url头部(大概这么叫可以吧)

    String url_beauty="http://api.tianapi.com/txapi/sentence/index?key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&";//“xxxxxxxxxxx..."替换为APIkey
    String url_garbage="http://api.tianapi.com/txapi/lajifenlei/index?key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&word=";

接着定义一个handler,用来发送信息,同时初始化网络:

    public void intn() {
        View view = getWindow().peekDecorView();
        if (view != null) {//这里是网络访问的代码,获取服务
            InputMethodManager inputmanger = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            inputmanger.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    }
    Handler handler_beauty=new Handler(new Handler.Callback() {//首先通过handler发送信息
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            switch (msg.what){
                case 0:
                    Toast.makeText(MainActivity.this,"网络错误",Toast.LENGTH_LONG).show();
                    break;
                case 1:
                    String json=(String)msg.obj;
                    try{
                        JSONObject js=new JSONObject(json);
                        String content=js.getString("content");
                        tv_beauty.setText(content);
                        break;
                    }catch (JSONException e){
                        e.printStackTrace();
                    }
            }
            return false;
        }
    });
    private void initData_beauty(){                 //接着用这个方法调用handler,并把返回的信息放入TextView
        handler_beauty.sendEmptyMessage(0);
        Okhttp_work.OkHttpGet(url_beauty, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String content=response.body().string();
                Message message=new Message();
                message.what=1;
                message.obj=content;
            }
        });
    }

最后在定义一个handler_time用于不断重复刷新我们的美句:

    private Handler handler_time=new Handler();
    private Runnable task=new Runnable() {
        @Override
        public void run() {
            handler_time.postDelayed(this,5*1000);
            initData_beauty();//这里放重复操作
        }
    };

最后在onCreate方法里调用handler_time:

handler_time.post(task);

好了,大功告成了,现在来测试一下,
… … … …
不出意外,我们的程序,成功闪退了

现在就是debug时间了,我先试着把这次添加的内容全部注释了,测试一下原程序可不可以跑,因为一直切换两个不同环境的程序让我有点害怕,不过结果很喜人,是可以跑的。
也就是说,错误出在我们添加的这一段代码上。
我的第一个猜测,就是没有申请网络服务,玩过手机盗版游戏的都知道,一些老游戏在打开之后会闪退,因为它不会自己申请权限,我们在设置里给它权限,就可以play了。所以我们先试试给权限之后,我们的程序能不能打开。

很明显问题没有那么简单,
我发现还要在AndroidManifest.xml中声明一下网络权限,所以在其中添加了如下代码:

    <uses-permission-sdk-23 android:name="android.permission.INTERNET"/>

再打开程序,好了一点,尽管依旧闪退,但是它发了一个提示:“网络错误”。是我们handler_beauty里面的第一种情况。
在手机中看数据,发现我们的程序用了805b的网络:

发生甚么事了????

在我测试了一个小时之后,还是没找到问题。

楼主决定今天就更新到这里了(因为已经12点30了)。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页