零基础小白开发app日志–“菜根易嚼”交易平台

第一章 需求分析,UI设计到前端框架搭建


前言

猝不及防的金融软件工程课程大作业,和两个小伙伴选择做一个校园二手交易以及兼职信息发布的平台app,集成身份认证,发布商品,聊天,购买,评论,搜索,推荐,账单分析等功能。

因为之前完全没有基础,也是边学边做。写app日志一个是为了给这段日子的摸索留下一段纪念,另一个目的也是为了后来的小白能有一个参考,经历过这些事才知道从零基础开始短时间开发上线一个app有多痛苦。

一、菜根易嚼是什么?

功能概述

“菜根易嚼”APP,英文名叫“EasytoChewRoot”
主要实现的功能在校园背景下,校园环境有可线下交易,对于用户的身份可以充分的信任。
app主要用于校园用户,手头上的闲置物品有一个方便的平台可以出售,想低价买商品也可以使用这个
app进行搜寻,还有智能推荐商品的功能。
同时,如果有人有空闲时间可以在上面发布兼职信息,如果需要别人的兼职服务也可以在上面交易。
app带有聊天沟通的功能,对使用app的账单还有个性化的分析。
当前很多时候需要个人的简历和介绍等,个人主页的方便性快捷性和优质的可视化使得个人主页的拥有
者越来越多,个人主页越来越流行。

目标用户

校园用户
需求分析
具体需要实现的功能有:发布商品,搜索商品,进行聊天,用户登录,用户注册,用户信息修改,商品推荐

技术栈

前端使用Android Studio开发,具体使用gradle架构
后端使用MySQL数据库,后端框架计划使用Spring boot

项目分工

myc 框架设计分析(需求+UI交互)+流程时序+前端开发+前后端连接
lxy 前端开发+连接服务器相关知识
czy 后端开发+app发布相关知识和流程

项目管理

使用git仓库对项目源代码进行管理,不同的操作人使用不同的分支来进行区分,最终对整个项目进行合并。

实现思路

项目的实现思路是由实际需求出发,对项目进行设计并且完成前端布局页面的具体功能,完成各个页面
之间的跳转等功能。在此过程中,还需要完成后端数据库的设计。在此基础上完成后端算法,对具体功
能需要实现的算法进行设计和完成。最终对项目进行发布,使之成为可实际使用的app。 期望成果
我们期望项目最终成为一个在校园内广为流行,有一定的用户量,能够服务校园用户的app。在整个app
中主要包含的功能模块有对商品管理模块、聊天模块、个人信息模块等。

UI以及数据传输设计

因为博主myc比较辣鸡,UI设计其实在做的过程中一直有略微的调整。为了防止买家秀和卖家秀,就不给出设计图片了,最后以实物为准。

数据传输因为目前okhttp与数据库的连接问题还在学习和解决中,所以在以后的

二、Android Studio使用经验

1.下载

去官网下载即可,地址如下
https://developer.android.google.cn/
注意如果电脑没有配置java环境,就直接下载附带SDK包的Android Studio即可。
如果电脑本身有SDK,也可以点进去下载软件的插件即可。

2.项目讲解

2.1配置文件

新建一个project后,会有一个新的这个app项目的配置文件,即AndroidManifest.xml文件,里面写入的是这个项目需要手机允许的权限请求以及该项目中创建的不同activity。
代码如下(示例):

<?xml version="1.0" encoding="utf-8"?>

manifest xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:tools=“http://schemas.android.com/tools”
package=“com.skypan.easytochewroot”>

<!-- 拍照 -->
<uses-permission android:name="android.permission.CAMERA" /> <!-- 读写 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.PERMISSIONS_STORAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
    android:allowBackup="true"
    android:icon="@drawable/iconico"
    android:label="@string/app_name"
    android:roundIcon="@drawable/iconico"
    android:supportsRtl="true"
    android:theme="@style/Theme.EasytoChewRoot">

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="com.skypan.easytochewroot"
    android:exported="false"
    android:grantUriPermissions="true"
    tools:ignore="MissingClass">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

    <meta-data
        android:name="com.google.android.actions"
        android:resource="@xml/file_paths" />

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".Myaty" />
    <activity android:name=".login" />
    <activity android:name=".Register" />
    <activity android:name=".Main_Page" />
    <activity android:name=".PersonInformation" />
    <activity android:name=".ChangePsw" />
    <activity android:name=".AboutUs" />
    <activity android:name=".MyRelase" />
    <activity android:name=".PublishGoods" />
    <activity android:name=".Page1" />
    <activity android:name=".Page2" />
    <activity android:name=".Page3" />
    <activity android:name=".Page4" />
    <activity android:name=".Page5" />
    <activity android:name=".Page6" />
    <activity android:name=".Page7" />
    <activity android:name=".Page8" />
    <activity android:name=".Page9" />
    <activity android:name=".Page10" />
    <activity android:name=".Item"/>
    <activity android:name=".Chatting"/>
    <activity android:name=".Searching"/>
</application>

2.2布局文件以及逻辑代码

然后其实需要了解的是,Android Studio采用的是gradle架构,gradle.build文件里会要添加要调用的包,需要的时候添加即可。

而对初学者写简单app,编码最多的一个是res文件夹里面的layout文件夹中的xml布局文件,这些文件决定了每一个app每一个相对静态界面的布局。示例如下,是一个发布商品界面的布局xml。

<?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">
    <LinearLayout tools:context="page.page1.AddItem" android:orientation="vertical" android:layout_height="match_parent" android:layout_width="match_parent" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"/>


    <RelativeLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_gravity="center_vertical" android:background="#1E90FF"
        tools:ignore="MissingConstraints">

    <!--Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:background="#1E90FF" android:text="首页" android:textSize="20dp" android:layout_alignParentLeft="true" android:gravity="center" android:id="@+id/but1_m1"/>

    <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="发布商品" android:textSize="30dp" android:gravity="center" android:textColor="#F0FFFF" android:layout_centerInParent="true"/>

    <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:background="#1E90FF" android:text="我的发布" android:textSize="20dp" android:gravity="center" android:id="@+id/but2_m1" android:layout_alignParentRight="true"
        android:spinnerMode="dialog"/-->

</RelativeLayout>


    <LinearLayout android:orientation="vertical" android:layout_height="wrap_content" android:layout_width="match_parent" android:gravity="center" android:layout_marginTop="15dp"
        tools:ignore="MissingConstraints">


</LinearLayout>



    <ScrollView

        android:id="@+id/scrollView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        tools:ignore="MissingConstraints">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="page.page1.AddItem"
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="-236dp">


        -

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:background="#1E90FF">

            <Button
                android:id="@+id/but1_m1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:background="#1E90FF"
                android:gravity="center"
                android:text="首页"
                android:textSize="20dp"
                tools:ignore="DuplicateIds" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:gravity="center"
                android:text="发布商品"
                android:textColor="#F0FFFF"
                android:textSize="30dp" />

            <Button
                android:id="@+id/but2_m1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:background="#1E90FF"
                android:gravity="center"
                android:text="我的发布"
                android:textSize="20dp"
                tools:ignore="DuplicateIds" />

        </RelativeLayout>



            -

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="15dp"
                android:gravity="center"
                android:orientation="vertical">
                <ImageView
                    android:id="@+id/photo_iv"
                    android:layout_width="143dp"
                    android:layout_height="85dp"
                    android:layout_marginTop="6dp"
                    android:src="@drawable/m1_sc"/>
                <Button
                    android:id="@+id/camera_bt"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="相机" />

                <Button
                    android:id="@+id/photo_bt"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="相册" />

                <!--TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="15dp"
                    android:gravity="center"
                    android:text="以下是展示相机拍照返回的图片" /-->

                <!--ImageView
                    android:id="@+id/camere_iv"
                    android:layout_width="139dp"
                    android:layout_height="87dp"
                    android:layout_marginTop="6dp" /-->

                <!--TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="15dp"
                    android:gravity="center"
                    android:text="以下是展示相册拍照返回的图片" /-->



            </LinearLayout>


            -

            <LinearLayout
                android:layout_width="340dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="20dp"
                android:orientation="vertical">


                -

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:text="标题"
                        android:textSize="20dp" />

                    <EditText
                        android:id="@+id/m1_title"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:layout_marginLeft="10dp"
                        android:minWidth="250dp"
                        android:textSize="20dp" />

                </LinearLayout>


                -

                <LinearLayout android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_marginTop="20dp">

                    <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_gravity="center" android:text="种类" android:textSize="20dp"/>

                    <Spinner android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="@+id/m1_style" android:layout_marginLeft="20dp" android:textAlignment="center"> </Spinner>

                </LinearLayout>


                -

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="20dp">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:text="价格"
                        android:textSize="20dp" />

                    <EditText
                        android:id="@+id/m1_price"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:layout_marginLeft="10dp"
                        android:minWidth="100dp"
                        android:textSize="20dp" />

                </LinearLayout>


                -

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="20dp">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:text="联系方式"
                        android:textSize="20dp" />

                    <EditText
                        android:id="@+id/m1_phone"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:layout_marginLeft="10dp"
                        android:minWidth="210dp"
                        android:textSize="20dp" />

                </LinearLayout>


                -

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="20dp">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:text="描述"
                        android:textSize="20dp" />

                    <EditText
                        android:id="@+id/m1_nr"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:layout_marginLeft="10dp"
                        android:minWidth="250dp"
                        android:textSize="20dp" />

                </LinearLayout>

            </LinearLayout>


            -

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center_vertical|center"
                android:orientation="vertical">

                <Button
                    android:id="@+id/fabu"
                    android:layout_width="400dp"
                    android:layout_height="wrap_content"
                    android:background="#1E90FF"
                    android:text="发布"
                    android:textSize="30dp" />

            </LinearLayout>

    </LinearLayout>
    </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

而对于布局里的控件,其有什么深层逻辑,以及布局页面其实是镶嵌在activity中生成的,调用java文件中继承的activity的类,去生成activity,选择布局xml,以及控制布局中的控件。示例如下,依然是发布商品页activity对应的java类文件。

package com.skypan.easytochewroot;

import android.app.Activity;
import android.os.Bundle;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.FileProvider;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;


import androidx.annotation.Nullable;

public class PublishGoods extends Activity {

    private Button cameraBt;
    private Button photoBt;
    private ImageView camereIv;
    private ImageView photoIv;
    private String TAG = "tag";
    //需要的权限数组 读/写/相机
    private static String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.CAMERA};

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

        Spinner spinner = (Spinner) findViewById(R.id.m1_style);
// 建立数据源
        String[] mItems = {"二手书", "自行车", "桌游", "化妆品","文具用品","快递代取","学习辅导","电子产品","软件权限"};
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, mItems);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);

        findViewById(R.id.but1_m1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(PublishGoods.this,Main_Page.class));
            }
        });
        findViewById(R.id.but2_m1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(PublishGoods.this,MyRelase.class));
            }
        });



        //跳转相机动态权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
            StrictMode.setVmPolicy(builder.build());
        }
        initView();
    }
    private Uri ImageUri;
    public static final int TAKE_PHOTO = 101;
    public static final int TAKE_CAMARA = 100;

    private void initView() {
        cameraBt = (Button) findViewById(R.id.camera_bt);
        photoBt = (Button) findViewById(R.id.photo_bt);
        camereIv = (ImageView) findViewById(R.id.photo_iv);
        photoIv = (ImageView) findViewById(R.id.photo_iv);

        cameraBt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //检查是否已经获得相机的权限
                if (verifyPermissions(PublishGoods.this, PERMISSIONS_STORAGE[2]) == 0) {
                    Log.i(TAG, "提示是否要授权");
                    ActivityCompat.requestPermissions(PublishGoods.this, PERMISSIONS_STORAGE, 3);
                } else {
                    //已经有权限
                    toCamera();  //打开相机
                }
            }
        });
        photoBt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                toPicture();
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case TAKE_PHOTO:
                if (resultCode == RESULT_OK) {
                    try {
                        //将拍摄的照片显示出来
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(ImageUri));
                        camereIv.setImageBitmap(bitmap);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case TAKE_CAMARA:
                if (resultCode == RESULT_OK) {
                    try {
                        //将相册的照片显示出来
                        Uri uri_photo = data.getData();
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri_photo));
                        photoIv.setImageBitmap(bitmap);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                break;
            default:
                break;
        }
    }


    /**
     * 检查是否有对应权限
     *
     * @param activity   上下文
     * @param permission 要检查的权限
     * @return 结果标识
     */
    public int verifyPermissions(Activity activity, java.lang.String permission) {
        int Permission = ActivityCompat.checkSelfPermission(activity, permission);
        if (Permission == PackageManager.PERMISSION_GRANTED) {
            Log.i(TAG, "已经同意权限");
            return 1;
        } else {
            Log.i(TAG, "没有同意权限");
            return 0;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (grantResults != null && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Log.i(TAG, "用户授权");
            toCamera();
        } else {
            Log.i(TAG, "用户未授权");
        }
    }

    //跳转相册
    private void toPicture() {
        Intent intent = new Intent(Intent.ACTION_PICK);  //跳转到 ACTION_IMAGE_CAPTURE
        intent.setType("image/*");
        startActivityForResult(intent, TAKE_CAMARA);
        Log.i(TAG, "跳转相册成功");
    }

    //跳转相机
    private void toCamera() {
        //创建File对象,用于存储拍照后的图片
//        File outputImage = new File(getExternalCacheDir(), "outputImage.jpg");
        File outputImage = new File(getExternalCacheDir(), System.currentTimeMillis() + ".jpg");
        if (outputImage.exists()) {
            outputImage.delete();
        } else {
            try {
                outputImage.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //判断SDK版本高低,ImageUri方法不同
        if (Build.VERSION.SDK_INT >= 24) {
            ImageUri = FileProvider.getUriForFile(PublishGoods.this, "com.skypan.easytochewroot", outputImage);
        } else {
            ImageUri = Uri.fromFile(outputImage);
        }

        //启动相机程序
        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, ImageUri);
        startActivityForResult(intent, TAKE_PHOTO);
    }
}

总结

因为后台和前端运行在我们三个人不同地电脑上,遗憾的是竟然没有一个人能同时运行我们组所有文件,所以本地传输测试没有成功。昨天进行了局域网传输,依然是石沉大海。现在准备尝试直接连接云端服务器,先尝试注册功能是否能够实现,希望能够成功,少掉写头发。

因为是小白,从开始接触到现在才10天左右,如果上面的描述有错误希望谅解。下面给出一些目前设计出的activity试样(仅给出少部分仅供参考)。
打开app的界面
商品主页界面
发布商品界面

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐