[Java] Getting started with Android!

11 minute read

Introduction

Hello, end of school this week full, spend the summer vacation with no contents from next week is my.
This time, I would like to actually use the Android app for HTTP communication with the Django API created in Previous article.

By the way, the quality is not so high because it was implemented in one day even though it was covered. (Although it takes about 16 hours)

Basics!

This is where I had the most trouble. I didn’t understand the execution configuration at all, I couldn’t see the whole picture at all, how to implement the front end? etc.
First of all, if you can’t grasp the whole picture, you don’t know what to start with. Therefore, first of all, it is necessary to understand what kind of structure it is made of and what it can do.

In addition, there are Kotlin and React Native recently when developing Android applications, but this time we will use Java, which is Owacon Legacy Language.

Important things

Here are some important things to do when creating an Android app.
At the very least, I want you to understand this configuration, so please forgive me.

–Activity
–Represents the overall flow of execution
–Override onCreate () on the main class to execute and execute
–After onCreate, onStart and onResume will be executed and the app will be in the running state.
-This site had an easy-to-understand explanation.
–Manifest
–The manifest file shows the Android settings.
–As I will write later, it is necessary to declare that the Internet will be used when performing HTTP communication.
–The name of the main class to be executed is also explicitly shown here (ExSample.java this time).
–In addition, when using an external API, write it here.

  • XML
    ――Define the part that makes the appearance.
    ――You can assign an ID to a part to correspond to the processing in the class, put a value in it, and raise an event.
    –Emulator
    –You can run it using a pseudo emulator without an Android device.
    ――If you have one, you should use the actual machine.
    ――In this article, I will omit the setting method of the emulator.

If a web lover compares it to MVC, this time the model is on Django’s server, the java code that makes up Android is the controller, and the part written in XML is the view.

Execution configuration

This time, I’m confident that this is the part I didn’t understand the most because of HTTP communication.
Which class is executed in Android in the first place? I was in trouble because it was like that.
As a major premise
** When you run Android, the class specified in the manifest will be executed. ** **
In other words, even if you define another class, you will eventually need to aggregate it there. (I didn’t understand this)

The image will look like the figure below.
image.png

It’s a dirty figure, but since the only class that is finally executed is the main class, even if there are many other classes, the processing that you want to do is executed only in the main class. You can make a detour, so let’s get to the main! !! !!

Let’s actually write the code.

The classes used this time are as follows.

class Use
ExSample.java Main execution class
AsyncHttpRequestGet.java Get all data
AsyncHttpRequestPost.java Send delivery completion notification
ListAndView.java Class for setting list view in linear layout

This time we will make an android application using these four.

  • Regarding the delivery completion notification, this is a little tampered with the API from the previous article.

create!

Let’s write.

Points in Example

–Construct a program by inheriting the AppCompatActivity class.
–Execute with onCreate method.
–As you will see later, when you use a layout like creating a table called ListView, you will use the Context of the main class, so create a getInstance method so that you can use it anywhere.
–The first get request is sent using AsyncHttpRequestGet.

ExSample.java


package es.exsample;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

public class ExSample extends AppCompatActivity {

    //Show class
    private static final String TAG = "ExSample";
    //Variables for referencing Context in different classes
    private static ExSample context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_item);
        context = this;
        //Run
        AsyncHttpRequestGet task = new AsyncHttpRequestGet(context);
        task.execute("http://localhost:8000/get_shop");
        Log.d(TAG, "created");
    }

    //Functions for using Context in other classes
    public static ExSample getInstance(){
        return context;
    }
}

Point of AsyncHttpRequestGet

–ExSample only executes this, so the amount in this class is rather large.
–Asynchronous processing is performed by inheriting AsyncTask.
–Initialize what is passed by specifying the ID of the XML part in the constructor.
–URL url = new URL (params [0]); can get the URL defined in the main class.
–Specify the header with setRequestProperty (This time, I created a token that is authenticated but persistent, so it is solid)
–If you put the received value in JSONArray, you can easily operate it.
–Substitute the context obtained by the method defined in the main class for the first argument of ArrayAdapter . (If you want to define the list view only in the main class, you can write this directly)

AsyncHttpRequestGet.java



package es.exsample;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;

public class AsyncHttpRequestGet extends AsyncTask<String, Void, String> {
    //Logger tag
    private static final String TAG = "AsyncHttpRequestGet";

    //View operated from UI thread
    private TextView titleView;
    private TextView beforUserContent;
    private TextView doneUserContent;
    private ListView beforUser;
    private ListView doneUser;
    public static Map<String, String> data;
    public static List<Map<String, String>> dataList;
    public static ListView listView;
    public static ListAndView adapter;

    //Set constructor, View
    public AsyncHttpRequestGet(Context context) {
        super();
        ExSample sample = (ExSample) context;
        titleView = (TextView)sample.findViewById(R.id.title);
        beforUserContent = (TextView)sample.findViewById(R.id.befor);
        doneUserContent = (TextView)sample.findViewById(R.id.done);
        beforUser = (ListView)sample.findViewById(R.id.beforUser);
        doneUser = (ListView)sample.findViewById(R.id.doneUser);

        listView = (ListView)sample.findViewById(R.id.beforUser);
    }

    //Handle requests and responses here
    @Override
    protected String doInBackground(String... params) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        HttpsURLConnection connection = null;

        try {
            //The URL is set, the header value is managed here, and the token can be obtained when logging in.
            URL url = new URL(params[0]);
            connection = (HttpsURLConnection)url.openConnection();
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Authorization", "Specify the key obtained by JWT Django");
            connection.setConnectTimeout(3000);
            connection.setReadTimeout(3000);

            // GET
            connection.setRequestMethod("GET");
            connection.connect();

            //Check the response code
            int responseCode = connection.getResponseCode();
            if(responseCode != HttpsURLConnection.HTTP_OK) {
                throw new IOException("HTTP responseCode: " + responseCode);
            }

            //Stringification
            inputStream = connection.getInputStream();
            if(inputStream != null) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(connection != null) {
                connection.disconnect();
            }
        }
        return sb.toString();
    }

    //Create a View here
    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    protected void onPostExecute(String result) {

        List<String> userListOrderDone = new ArrayList<String>();
        List<String> userListBeforOrder = new ArrayList<String>();
        List<String> idList = new ArrayList<String>();

        //A function that just returns this in ExSample (I don't know if it makes sense)
        Context context = ExSample.getInstance().getApplicationContext();
        ArrayAdapter<String> beforUserList = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, userListBeforOrder);
        ArrayAdapter<String> doneUserList = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, userListOrderDone);


        Log.d(TAG, result);
        titleView.setText("Motodeli");
        beforUserContent.setText("Before delivery");
        doneUserContent.setText("Delivery completed");
        beforUser.setAdapter(beforUserList);
        doneUser.setAdapter(doneUserList);


        try{
            //Get all responses with JSONArray
            JSONArray all = new JSONArray(result);
            dataList = new ArrayList<Map<String, String>>();
            for(int i = 0; i < all.length(); i++){
                data = new HashMap<String, String>();
                //You can get each desired value
                JSONObject json = all.getJSONObject(i);
                String email = json.getString("user");
                String total = json.getString("total");
                String status = json.getString("status");
                String id = json.getString("id");
                //Judge whether it has been delivered or delivered according to the user's condition (an image that many beginners are addicted to comparing Java strings)
                if(status.equals("true")){
                    data.put("text1", email);
                    data.put("text2", id);
                    dataList.add(data);
                }
                else{
                    userListOrderDone.add(String.format("%s: %s yen", email, total));
                }
            }
        }
        catch (JSONException e){
            System.out.println(e);
        }

        //Enter the value based on the data extracted earlier
        adapter = new ListAndView(
                context,
                dataList,
                R.layout.row,
                new String[] {
                        "text1",
                        "text2",
                    },
                new int[] {
                        android.R.id.text1,
                        android.R.id.text2,
                });
        //Reflected in list view
        listView.setAdapter(adapter);
        listView.setTextFilterEnabled(false);
    }
}

Point of AsyncHttpRequestPost

–Almost the same as AsyncHttpRequestGet.
–Because it is a post request, there is no need to mold the value.
–Backend changes will be described later.

AsyncHttpRequestPost.java


package es.exsample;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;

public class AsyncHttpRequestPost extends AsyncTask<String, Void, String> {
    private static final String TAG = "AsyncHttpRequestPost";
    private TextView textView;

    public AsyncHttpRequestPost(Context context) {
        super();
    }

    @Override
    protected String doInBackground(String... params) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        HttpsURLConnection connection = null;

        try {
            //Set the URL string.
            URL url = new URL(params[0]);
            connection = (HttpsURLConnection)url.openConnection();
            connection.setConnectTimeout(3000); //Timeout 3 seconds
            connection.setReadTimeout(3000);

            // POST
             connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Authorization", "JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo2LCJ1c2VybmFtZSI6ImIxODA2NDI5QHBsYW5ldC5rYW5hemF3YS1pdC5hYy5qcCIsImV4cCI6MTU5NTIzMTIzNiwiZW1haWwiOiJiMTgwNjQyOUBwbGFuZXQua2FuYXphd2EtaXQuYWMuanAifQ.18LotiLgemUmSXTqmdcjjD3eKLSL1B13N87msbQswoE");
            OutputStream outputStream = connection.getOutputStream();
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
            writer.write(params[1]);
            writer.close();
            connection.connect();

            //Response code.
            int responseCode = connection.getResponseCode();
            if(responseCode != HttpsURLConnection.HTTP_OK) {
                throw new IOException("HTTP responseCode: " + responseCode);
            }

            //Stringification
            inputStream = connection.getInputStream();
            if(inputStream != null) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(connection != null) {
                connection.disconnect();
            }
        }
        return sb.toString();
    }

}

ListAndView points

–Created by inheriting SimpleAdapter.
–Execute post using AsyncHttpRequestPost.
–It is designed to be executed when the button is pressed using the onClick method.

ListAndView.java


package es.exsample;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.SimpleAdapter;
import android.widget.TextView;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static android.content.ContentValues.TAG;

public class ListAndView extends SimpleAdapter {

    private LayoutInflater inflater;
    private List<? extends Map<String, ?>> listData;

    //Data retention class held by each row
    public class ViewHolder {
        TextView text1;
        TextView text2;
    }

    public ListAndView(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
        super(context, data, resource, from, to);
        this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.listData = data;
    }


    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;

        //Receive a view
        View view = convertView;

        if (view == null) {
            view = inflater.inflate(R.layout.row, parent, false);

            holder = new ViewHolder();
            holder.text1 = (TextView) view.findViewById(android.R.id.text1);
            holder.text2 = (TextView) view.findViewById(android.R.id.text2);
            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }

        //Set data in holder
        String text1 = ((HashMap<?, ?>) listData.get(position)).get("text1").toString();
        String text2 = ((HashMap<?, ?>) listData.get(position)).get("text2").toString();
        holder.text1.setText(text1);
        holder.text2.setText(text2);

        //Execute when you press the button
        Button btn = (Button) view.findViewById(R.id.rowbutton);
        btn.setTag(position);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                String id = holder.text2.getText().toString();
                Context context = ExSample.getInstance().getApplicationContext();
                AsyncHttpRequestPost task = new AsyncHttpRequestPost(context);
                String url = "http://localhost:8000/post_shop/" + id;
                task.execute(url, "hi");
                Log.d(TAG, "created");
            }
        });

        return view;
    }

}

XML

  • list_item.xml
    ――It is responsible for the overall composition.
    –Implemented with a linear layout.

image.png

list_item.xml


<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/cardView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="10dp"
    card_view:cardBackgroundColor="#ffffff"
    card_view:cardCornerRadius="7dp"
    card_view:cardElevation="5dp">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="1542dp">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView"
            android:textSize="24sp"
            card_view:layout_constraintBottom_toBottomOf="parent"
            card_view:layout_constraintEnd_toEndOf="parent"
            card_view:layout_constraintHorizontal_bias="0.498"
            card_view:layout_constraintStart_toStartOf="parent"
            card_view:layout_constraintTop_toTopOf="parent"
            card_view:layout_constraintVertical_bias="0.01"
            />

        <TextView
            android:id="@+id/befor"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:text="TextView"
            card_view:layout_constraintTop_toBottomOf="@+id/title"
            tools:layout_editor_absoluteX="189dp"
            />

        <ListView
            android:id="@+id/beforUser"
            android:layout_width="402dp"
            android:layout_height="130dp"
            android:background="#7A7A7A"
            card_view:layout_constraintEnd_toEndOf="parent"
            card_view:layout_constraintStart_toStartOf="parent"
            card_view:layout_constraintTop_toBottomOf="@+id/befor" />



        <TextView
            android:id="@+id/done"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="TextView"
            card_view:layout_constraintTop_toBottomOf="@+id/beforUser"
            tools:layout_editor_absoluteX="189dp" />

        <ListView
            android:id="@+id/doneUser"
            android:layout_width="402dp"
            android:layout_height="364dp"
            android:layout_marginTop="12dp"
            android:background="#777777"
            card_view:layout_constraintEnd_toEndOf="parent"
            card_view:layout_constraintStart_toStartOf="parent"
            card_view:layout_constraintTop_toBottomOf="@+id/done" />

        <TextView
            android:id="@+id/tag"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="60dp"
            android:text="TextView"
            card_view:layout_constraintTop_toBottomOf="@+id/doneUser"
            tools:layout_editor_absoluteX="98dp" />

        <TextView
            android:id="@+id/desc"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="100dp"
            android:layout_marginTop="60dp"
            android:text="TextView"
            card_view:layout_constraintStart_toEndOf="@+id/tag"
            card_view:layout_constraintTop_toBottomOf="@+id/doneUser" />

    </android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
  • row.xml
    –Making the contents of each list

    image.png

row.xml


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="80dp"
        tools:ignore="MissingConstraints">

        <TextView
            android:id="@android:id/text1"
            android:layout_width="278dp"
            android:layout_height="80dp"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:text="Text1"
            android:textSize="18dp" />

        <TextView
            android:id="@android:id/text2"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center_vertical|right"
            android:text="Text2"
            android:textSize="18dp" />

        <Button
            android:id="@+id/rowbutton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:focusable="false"
            android:focusableInTouchMode="false"
            android:text="Delivered!" />

    </LinearLayout>

</android.support.constraint.ConstraintLayout>

It’s a bit messy, but I hope you can actually copy and use it!

Django backend changes (post execution)

–Created a function to notify the administrator when delivery is completed.
–When you press the AsyncHttpRequestPost button, the process jumps to that endpoint, emptying the cart of the user who owns the selected cart and skipping the mail. (The email part is omitted)
–The cart ID is specified by the argument pk.

shop/views.py


######
###abridgement###

#Add the following

from rest_framework.decorators import api_view

@api_view(['POST'])
def order_done_post_request(request, pk):
    user_info = UserInfomation.objects.get(id=pk)
    user = User.objects.get(email=user_info)
    if request.method == 'POST':
        cart = Cart.objects.get(cart_id=user_info.cart.cart_id)

        order_done(request, str(cart))
    
        user = user_info
        #Cart management is implemented by putting a negative value instead of logical deletion (mystery)
        cart.cart_id = -cart.cart_id
        user.status = None
        cart.save()
        user.save()
        return Response(None) #You don't have to return anything

###abridgement###

Specify the cart ID by specifying the int type pk

shop/urls.py



urlpatterns = [
    ###abridgement###
    path('post_shop/<int:pk>', views.order_done_post_request,),  #add to
]

The above is the content that I worked hard to implement in one day after Android Studio was revived. When I tried to write an article in this way, the amount of sentences became very large, even though there were many parts omitted.

Summary

It takes a day just to create such a simple application, and the environment construction is awkward, so engineers are impressed every time. This time it was Android, but I would like to work on iOS soon. It is impossible unless you buy a new computer.
It’s a pretty messy article, so if you have any questions, please send them in the comments or on Twitter’s DM! After that, please comment if there are any mistakes or omissions!

Good summer vacation for all the students! !! !!