0

I have just started Android programming about a few weeks ago and was tasked to write a program to send a HTTP GET request to an external WeMos D1 mini pro for processing for upload to an internal SQL database.

This is my code for the main activity

package com.sp.androidesp8266wifi;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ToggleButton;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;


public class MainActivity extends Activity implements View.OnClickListener {

public final static String PREF_IP = "PREF_IP_ADDRESS";
public final static String PREF_PORT = "PREF_PORT_NUMBER";


// declare buttons and text inputs
private ToggleButton        buttonPin2,buttonPin3,buttonPin4,buttonPin5,buttonPin6,buttonPin7;
// shared preferences objects used to save the IP address and port so that the user doesn't have to
// type them next time he/she opens the app.

private EditText editTextIPAddress, editTextPortNumber;
SharedPreferences.Editor editor;
SharedPreferences sharedPreferences;

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

    sharedPreferences = getSharedPreferences("HTTP_HELPER_PREFS",Context.MODE_PRIVATE);
    editor = sharedPreferences.edit();

    // assign buttons
    buttonPin2 = (ToggleButton)findViewById(R.id.buttonPin2);
    buttonPin3 = (ToggleButton)findViewById(R.id.buttonPin3);
    buttonPin4 = (ToggleButton)findViewById(R.id.buttonPin4);
    buttonPin5 = (ToggleButton)findViewById(R.id.buttonPin5);
    buttonPin6 = (ToggleButton)findViewById(R.id.buttonPin6);
    buttonPin7 = (ToggleButton)findViewById(R.id.buttonPin7);


    // set button listener (this class)
    buttonPin2.setOnClickListener(this);
    buttonPin3.setOnClickListener(this);
    buttonPin4.setOnClickListener(this);
    buttonPin5.setOnClickListener(this);
    buttonPin6.setOnClickListener(this);
    buttonPin7.setOnClickListener(this);

    // get the IP address and port number from the last time the user used the app,
    // put an empty string "" is this is the first time.
    editTextIPAddress = (EditText)findViewById(R.id.editTextIPAddress);
    editTextPortNumber = (EditText)findViewById(R.id.editTextPortNumber);

    editTextIPAddress.setText(sharedPreferences.getString(PREF_IP,""));
    editTextPortNumber.setText(sharedPreferences.getString(PREF_PORT,""));
}




@Override
public void onClick(View view) {

    // get the ip address
    String ipAddress = editTextIPAddress.getText().toString().trim();
    // get the port number
    String portNumber = editTextPortNumber.getText().toString().trim();


    // save the IP address and port for the next time the app is used
    editor.putString(PREF_IP,ipAddress); // set the ip address value to save
    editor.putString(PREF_PORT,portNumber); // set the port number to save
    editor.commit(); // save the IP and PORT

    // get the pin number
    String parameterValue = "";
    String parameter = "";


    // get the pin number from the button that was clicked
    if(view.getId()==buttonPin2.getId())
    {
        if (buttonPin2.getText().equals("ON"))
        {
            parameter = "2";
            parameterValue = "1";
        }
    }
    else if(view.getId()==buttonPin3.getId())
    {
        if (buttonPin3.getText().equals("ON"))
        {
            parameter = "3";
            parameterValue = "1";
        }
    }
    else if(view.getId()==buttonPin4.getId())
    {
        if (buttonPin4.getText().equals("ON"))
        {
            parameter = "4";
            parameterValue = "1";
        }
    }
    else if(view.getId()==buttonPin5.getId())
    {
        if (buttonPin5.getText().equals("ON"))
        {
            parameter = "5";
            parameterValue = "1";
        }
    }
    else if(view.getId()==buttonPin6.getId())
    {
        if (buttonPin6.getText().equals("ON"))
        {
            parameter = "6";
            parameterValue = "1";
        }
    }
    else if(view.getId()==buttonPin7.getId())
    {
        if (buttonPin7.getText().equals("ON"))
        {
            parameter = "7";
            parameterValue = "1";
        }
    }

    Intent intent = new Intent("com.sp.androidesp8266wifi.ServiceStatusUpdate");
    intent.putExtra("parameterValue", parameterValue);
    intent.putExtra("ipAddress", ipAddress);
    intent.putExtra("portNumber", portNumber);
    intent.putExtra("parameter", parameter);

    // execute HTTP request
    if(ipAddress.length()>0 && portNumber.length()>0) {
        startService(intent);
    }
}

/**
 * Description: Send an HTTP Get request to a specified ip address and port.
 * Also send a parameter "parameterName" with the value of "parameterValue".
 * @param parameterValue the pin number to toggle
 * @param ipAddress the ip address to send the request to
 * @param portNumber the port number of the ip address
 * @param parameterName
 * @return The ip address' reply text, or an ERROR message is it fails to receive one
 */
 /*  public String sendRequest(String parameterValue, String ipAddress, String portNumber, String parameterName) {
    String serverResponse = "ERROR";

    try {

        HttpClient httpclient = new DefaultHttpClient(); // create an HTTP client
        // define the URL e.g. http://myIpaddress:myport/?pin=13 (to toggle pin 13 for example)
        URI website = new URI("http://"+ipAddress+":"+portNumber+"/"+parameterName+"/"+parameterValue);
        HttpGet getRequest = new HttpGet(); // create an HTTP GET object
        getRequest.setURI(website); // set the URL of the GET request
        HttpResponse response = httpclient.execute(getRequest); // execute the request
    } catch (ClientProtocolException e) {
        // HTTP error
        serverResponse = e.getMessage();
        e.printStackTrace();
    } catch (IOException e) {
        // IO error
        serverResponse = e.getMessage();
        e.printStackTrace();
    } catch (URISyntaxException e) {
        // URL syntax error
        serverResponse = e.getMessage();
        e.printStackTrace();
    }
    // return the server's reply/response text
    return serverResponse;
} */

/**
 * An AsyncTask is needed to execute HTTP requests in the background so that they do not
 * block the user interface.
 */
 /* private class HttpRequestAsyncTask extends AsyncTask<Void, Void, Void> {

    // declare variables needed
    private String ipAddress, portNumber;
    private Context context;
    private String parameter;
    private String parameterValue;

    /**
     * Description: The asyncTask class constructor. Assigns the values used in its other methods.
     * @param context the application context, needed to create the dialog
     * @param parameterValue the pin number to toggle
     * @param ipAddress the ip address to send the request to
     * @param portNumber the port number of the ip address
     */
     /*public HttpRequestAsyncTask(Context context, String parameterValue,     String ipAddress, String portNumber, String parameter)
    {
        this.context = context;

        this.ipAddress = ipAddress;
        this.parameterValue = parameterValue;
        this.portNumber = portNumber;
        this.parameter = parameter;
    } */

    /**
     * Name: doInBackground
     * Description: Sends the request to the ip address
     * @param voids
     * @return
     */
    /*@Override
    protected Void doInBackground(Void... voids) {
        new Handler().postDelayed(new Runnable() {
            public void run() {
                sendRequest(parameterValue,ipAddress,portNumber, parameter);
            }
        }, 4000);

        return null;
    }



    /**
     * Name: onPostExecute
     * Description: This function is executed after the HTTP request returns from the ip address.
     * The function sets the dialog's message with the reply text from the server and display the dialog
     * if it's not displayed already (in case it was closed by accident);
     * @param aVoid void parameter
     */


    /**
     * Name: onPreExecute
     * Description: This function is executed before the HTTP request is sent to ip address.
     * The function will set the dialog's message and display the dialog.
     */


}

And this is my service java file

package com.sp.androidesp8266wifi;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.IBinder;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class ServiceStatusUpdate extends Service {

String ipAddress, parameter,parameterValue,portNumber;

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if   (intent.getAction().equals("com.sp.androidesp8266wifi.ServiceStatusUpdate")) {
        ipAddress = intent.getStringExtra("ipAddress");
        parameter = intent.getStringExtra("parameter");
        parameterValue = intent.getStringExtra("parameterValue");
        portNumber = intent.getStringExtra("portNumber");

        while (true) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                new DoBackgroundTask().execute();
                e.printStackTrace();
            }
        }
    }
    return START_STICKY;
}

public class DoBackgroundTask extends AsyncTask<Void, Void, Void> {


    public void sendRequest(String parameterValue, String ipAddress, String portNumber, String parameterName) {

        try {

            HttpClient httpclient = new DefaultHttpClient(); // create an HTTP client
            // define the URL e.g. http://myIpaddress:myport/?pin=13 (to toggle pin 13 for example)
            URI website = new URI("http://"+ipAddress+":"+portNumber+"/"+parameterName+"/"+parameterValue);
            HttpGet getRequest = new HttpGet(); // create an HTTP GET object
            getRequest.setURI(website); // set the URL of the GET request
            HttpResponse response = httpclient.execute(getRequest); // execute the request

        } catch (ClientProtocolException e) {
            // HTTP error
            e.printStackTrace();
        } catch (IOException e) {
            // IO error

            e.printStackTrace();
        } catch (URISyntaxException e) {
            // URL syntax error
            e.printStackTrace();
        }

    }

    @Override
    protected Void doInBackground(Void... params) {
        sendRequest(parameterValue,ipAddress,portNumber,parameter);
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {

        new Handler().postDelayed(new Runnable() {
            public void run() {
                sendRequest(parameterValue,ipAddress,portNumber, parameter);
            }
        }, 5000);
    }
}
}

and my Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sp.androidesp8266wifi">

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

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <service android:name=".ServiceStatusUpdate"></service>
</application>

</manifest>

I just started programming as an assignment and did not know of the functions available on Android. Hence, I did some research and came out with this program, but it crashes every time I press a button.

The objective of the program is to continuously send HTTP GET requests with the corresponding parameters to the WeMos after clicking the toggle button. I was wondering if Android can support multiple toggle-button being turned on at the same time and send requests simultaneously. Please help me and guide me on my starting journey. Thank you

  • 2
    "it crashes" -- use LogCat to examine the Java stack trace associated with your crash: https://stackoverflow.com/questions/23353173/unfortunately-myapp-has-stopped-how-can-i-solve-this – CommonsWare Jan 19 '17 at 12:42
  • Thanks, it was an "Service Intent must be explicit: Intent" error which I resolved using "intent setpackage". However, the app launches but the Wemos was unable to receive any GET requests when I press the button – Chung Loong Jan 19 '17 at 13:15

1 Answers1

0

in the main activity you start the service whenever the button is clicked

public void onClick(View view) {

[...]

Intent intent = newIntent("com.sp.androidesp8266wifi.ServiceStatusUpdate");
intent.putExtra("parameterValue", parameterValue);
intent.putExtra("ipAddress", ipAddress);
intent.putExtra("portNumber", portNumber);
intent.putExtra("parameter", parameter);

// execute HTTP request
if(ipAddress.length()>0 && portNumber.length()>0) {
    startService(intent);
}

then one instance of the service is running and does not stop. one not so good possibility is to add a this.stopSelf(); into the service so that whenever an instance of the service is started stops itself (http://www.stackoverflow.com/questions/1886874/how-to-stop-service-by-itself)

another solution is to send a message (event) from the activity to the background service that contains the information for the http request.

in this case you do not start the background service on button click. you start the service once in the main activity and then send a message to the service whenever a button is clicked

an example is in Example: Communication between Activity and Service using Messaging and https://blog.heckel.xyz/2012/06/10/android-example-communication-between-activity-and-service-using-messaging/

Community
  • 1
  • 1
ralf htp
  • 9,149
  • 4
  • 22
  • 34