2018/11/15

[Android] Send a Request to Website

Android 要如何傳送檔案要求到網站,本篇用一個開放測試的 Web API (Empath API) 來示範。 Empath 是一個可以透過聲音來辨識情緒的AI,它開放了一個 EmpathAPI 來讓使用者可以測試。
This tutorial is to teach how to develop empath API for Android.
Official Website: https://webempath.com/ 
Developer Website: https://webempath.net/sign_in
1. Sign up an development account for free.
2. Log in to the development page.
3. Go to API Keys and Add a new API Key.

4. Follow the WebAPI Specifications Document to develop.

5. Prepare the proper sound files for testing.
6. Create an Android project.
6.1. Use okhttp3 request tool in Android to send the sound file to the web.
6.2. Insert the endpoint URL and APIKEY apply to the web.
6.3. Get the responses message from the web.

AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

build.gradle:
dependencies {
    ........
    implementation 'com.squareup.okhttp3:okhttp:3.9.0' // okhttp
}

MainActivity:
package com.example.chris.myapplication;

import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import lib.folderpicker.FolderPicker;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity{

    private String TAG = "MainActivity";

    private TextView tv_show, tv_filename;

    private String EMPATH_ENDPOINT = "https://api.webempath.net/v2/analyzeWav";
    private String EMPATH_APIKEY = "hi2IaUFb7FUg8CLjBCcF-gubmihVtTgJX4bJcZLHxFE";
    private String filePath = "/storage/emulated/0/Empath/";
    private String fileName = "sound_01.wav";
    private String readFile = "";

    private Handler handler = null;
    private final int MSG_GET_EMOTION = 1010;
    private final int MSG_FAIL_GET_EMOTION = 1020;
    private final int PICKFILE_RESULT_CODE = 1;


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

        tv_show = (TextView)findViewById(R.id.id_tv_result);
        tv_filename = (TextView)findViewById(R.id.id_tv_filename);

        readFile = filePath+fileName;

        handler = new Handler(new Handler.Callback(){
            @RequiresApi(api = Build.VERSION_CODES.KITKAT)
            @Override
            public boolean handleMessage(Message message) {
                switch (message.what){
                    case MSG_GET_EMOTION:
                        //createSuperTikyuJin((JSONObject)message.obj);
                        Log.d(TAG, "send success");
                        break;
                    case MSG_FAIL_GET_EMOTION:
                        Toast.makeText(getApplicationContext(), "", Toast.LENGTH_LONG).show();
                        break;
                }
                return false;
            }
        });
    }

    public void onClickPlaySound(View v){
        MediaPlayer mp = MediaPlayer.create(this, Uri.parse(readFile));
        switch (v.getId()){
            case R.id.id_btn_play01:
                mp.start();
                break;
        }
    }

    public void onClickTest(View v){
        switch (v.getId()){
            case R.id.id_btn_test01:
                break;
        }
        new GetEmotion().execute();
    }

    public void onClickAttachFile(View v){
        Intent intent = new Intent(this, FolderPicker.class);
        //To show a custom title
        intent.putExtra("title", "Select file to upload");

        //To begin from a selected folder instead of sd card's root folder. Example : Pictures directory
        intent.putExtra("location", filePath);

        //To pick files
        intent.putExtra("pickFiles", true);
        startActivityForResult(intent, PICKFILE_RESULT_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent)
    {
        if (requestCode == PICKFILE_RESULT_CODE && resultCode == Activity.RESULT_OK) {
            String folderLocation = intent.getExtras().getString("data");
            tv_filename.setText(folderLocation);
            readFile = folderLocation;
        }
    }

    private class GetEmotion extends AsyncTask {

        private String result = null;

        @Override
        protected Long doInBackground(String... strings) {
            try{
                OkHttpClient client = new OkHttpClient();

                File file = new File(readFile);
                if(file.exists()){
                    Log.d(TAG,"file load success");
                }
                else{
                    Log.d(TAG,"File not found!");
                }

                RequestBody requestBody = new MultipartBody.Builder()
                        .setType(MultipartBody.FORM)
                        .addFormDataPart("apikey", EMPATH_APIKEY)
                        .addFormDataPart("wav", fileName, RequestBody.create(MediaType.parse("multipart/form-data"), file))
                        .build();
                Request request = new Request.Builder().url(EMPATH_ENDPOINT).post(requestBody).build();

                Response response = client.newCall(request).execute();
                if(response.isSuccessful()){
                    Log.d(TAG, "Response success");
                }
                this.result = response.body().string();
                return 0L;
            }catch(Exception e){
                result = "error";
                return 1L;
            }
        }

        @Override
        protected void onPostExecute(Long result) {
            super.onPostExecute(result);
            if (result == 0L){
                try {
                    // get json file
                    Log.d(TAG, "json: " + this.result);
                    tv_show.setText("result:" + this.result);

                    JSONObject json = new JSONObject(this.result);
                    Message msg = Message.obtain();
                    msg.what = MSG_GET_EMOTION;
                    msg.obj = json;
                    handler.sendMessage(msg);
                } catch (JSONException e) {
                    Message msg = Message.obtain();
                    msg.what = MSG_FAIL_GET_EMOTION;
                    handler.sendMessage(msg);
                    e.printStackTrace();
                }
            }
        }
    }
}

activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
    tools:context="com.example.chris.myapplication.MainActivity">

    <TextView
        android:id="@+id/id_tv_result"
        android:layout_width="348dp"
        android:layout_height="86dp"
        android:layout_marginStart="4dp"
        android:layout_marginTop="168dp"
        android:text="Test Sound"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/id_btn_play01"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_marginStart="4dp"
        android:layout_marginTop="104dp"
        android:onClick="onClickPlaySound"
        android:text="PLAY"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/id_btn_test01"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_marginStart="112dp"
        android:layout_marginTop="104dp"
        android:onClick="onClickTest"
        android:text="TEST"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/id_btn_attach"
        android:layout_width="wrap_content"
        android:layout_height="49dp"
        android:layout_marginStart="4dp"
        android:layout_marginTop="4dp"
        android:onClick="onClickAttachFile"
        android:text="file"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/id_tv_filename"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginTop="60dp"
        android:text="TextView"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>


APP執行結果:


END

沒有留言:

張貼留言