HTTP Get Example

This example shows how to perform a HTTP GET request.

A screenshot of the application.

We import the classes and modules that will be needed by the application. The most relevant are the classes from the java.net module.

from java.lang import Exception, Math, String
from java.io import BufferedInputStream, FileNotFoundException, IOException
from java.net import HttpURLConnection, URL
from android.app import Activity
from android.content import Context
from android.graphics import BitmapFactory
from android.os import Build, Bundle
from android.view import View, ViewGroup
from android.widget import Button, LinearLayout, ImageView, Toast
from android.net import ConnectivityManager
from android.util import Log

We define a class based on the standard Activity class. This represents the application, and will be used to present a graphical interface to the user.

class HTTPGetActivity(Activity):

    __interfaces__ = [View.OnClickListener]

The activity implements an interface to handle clicks on views.

The initialisation method simply calls the base class implementation.

    def __init__(self):
        Activity.__init__(self)

The onCreate method calls the base class implementation before obtaining a reference to the connectivity service and setting up the user interface.

    @args(void, [Bundle])
    def onCreate(self, bundle):
    
        Activity.onCreate(self, bundle)

We obtain an object that gives us access to the connectivity service. Since the method used to obtain this object does not specify the specific type of the manager object, we need to cast it explicitly to the correct type so that we can access its methods.

        service = self.getSystemService(Context.CONNECTIVITY_SERVICE)
        self.manager = CAST(service, ConnectivityManager)

We set up the user interface: just a button that is used to request an image to be fetched from a website, and a view that is used to display it.

        self.button = Button(self)
        self.button.setText("Fetch (HTTP GET)")
        self.button.setOnClickListener(self)
        
        self.imageView = ImageView(self)

The views are placed in a layout that is the main content shown by the activity.

        layout = LinearLayout(self)
        layout.setLayoutParams(ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT))
        layout.setOrientation(LinearLayout.VERTICAL)
        
        layout.addView(self.button)
        layout.addView(self.imageView)
        
        self.setContentView(layout)

We implement the onClick method to provide the View.OnClickListener interface that we declared earlier. This responds to clicks on the button that we created in the previous method.

    def onClick(self, view):

Currently, we have only implemented support for older versions of the connectivity API, so we check for those before checking whether the device has access to the Internet.

        if Build.VERSION.SDK_INT < 23:
            info = self.manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
            if info == None or not info.isConnected():
                Toast.makeText(self, "Not connected", Toast.LENGTH_SHORT).show()
                return
        else:
            Toast.makeText(self, "Not supported\nPlease update the example code.", Toast.LENGTH_SHORT).show()
            return

If the device is able to access online resources, we use it to fetch an image from a website. We specify the URL of the resource and use the URL object to open a connection to the server hosting it. We cast the connection object to a HttpURLConnection object so that we can enable request redirections.

        url = URL("http://www.boddie.org.uk/david/www-repo/Personal/Updates/2016/images/duck-small.png")
        connection = CAST(url.openConnection(), HttpURLConnection)
        connection.setInstanceFollowRedirects(True)

We obtain the length of the content from the connection and check to see if it is reasonable, showing a message and returning if not.

        length = connection.getContentLength()
        
        if length <= 0:
            Toast.makeText(self, "Invalid content length", Toast.LENGTH_SHORT).show()
            return

We use a stream to read the content, storing it in an array of the required length or showing an error message and returning if the stream cannot be opened.

        try:
            stream = BufferedInputStream(connection.getInputStream())
        except FileNotFoundException:
            Toast.makeText(self, "Resource not found", Toast.LENGTH_SHORT).show()
            return
        
        a = array(byte, length)
        total = 0

We loop until we have read all the content, storing new data after that we have already read, and requesting as much as possible. When all the data has been read, we close the stream.

        while total < length:
            total += stream.read(a, total, length - total)
        
        stream.close()

Since the content should be a PNG image, we decode it using a static BitmapFactory method, but for safety we only set the image on the ImageView if we obtain a valid bitmap.

        bitmap = BitmapFactory.decodeByteArray(a, 0, total)
        if bitmap != None:
            self.imageView.setImageBitmap(bitmap)

Files