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)
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.
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.
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.
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.
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.
Let's write.
--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;
}
}
--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
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);
}
}
--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();
}
}
--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
<?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
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!
--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.
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! !! !!
Recommended Posts