This example shows how to find and load a class from a library and call its methods.
We import the classes that will be needed by the application. The most relevant
to this example is the ClassLoader
class.
from java.lang import Boolean, Class, ClassLoader, ClassNotFoundException, \
Long, NoSuchMethodException, Object, String
from java.lang.reflect import Method
from android.view import View
from android.widget import Button, ScrollView, TextView
from serpentine.activities import Activity
from serpentine.widgets import VBox
We define a class based on a custom Activity class provided by the serpentine package. This represents the application, and will be used to present a graphical interface to the user.
The class declares the use of the View.OnClickListener
interface so that it
can respond to button clicks. It also declares a field, method
, that will
contain a reference to the method that will be called when the user clicks the
button; initially this is undefined.
class MethodCallActivity(Activity):
__interfaces__ = [View.OnClickListener]
__fields__ = {"method": Method}
CLASS = "android.os.Vibrator"
CHECK_METHOD = "hasVibrator"
METHOD = "vibrate"
DURATION = 500 # ms
We define the names of the class and two of its methods that we wish to call, as well as an argument that we will pass to the second method.
The initialisation method simply calls the corresponding method in the base class. This must be done even if no other code is included in the method.
def __init__(self):
Activity.__init__(self)
We use the onCreate
method to set up the user interface which consists
of a label, showing the method name, and a button for executing the method.
def onCreate(self, bundle):
Activity.onCreate(self, bundle)
label = TextView(self)
label.setText(self.CLASS)
self.button = Button(self)
self.button.setText(self.METHOD)
self.button.setOnClickListener(self)
layout = VBox(self)
layout.addView(label)
layout.addView(self.button)
self.setContentView(layout)
self.getClassAndMethod()
We finish the initialisation by calling a method to obtain information about the class and its method that we want to call.
The method called is given below. We begin by obtaining an instance of the
class whose method we will call and initialising the method
field defined
earlier.
def getClassAndMethod(self):
self.vibrator = self.getSystemService(self.VIBRATOR_SERVICE)
self.method = None
In a try
...except
structure we load the class and query it for
the methods we want to call. The first, hasVibrator
, returns a
boolean value that is presented to us as a "boxed" Boolean
value.
try:
cl = self.vibrator.getClass()
hasVibrator = cl.getMethod(self.CHECK_METHOD, array(Class, 0))
result = hasVibrator.invoke(self.vibrator, array(Object, 0))
if not CAST(result, Boolean).booleanValue():
self.button.setEnabled(False)
return
If the result of the method call is False
then we disable the
button and return. Otherwise, we can proceed by obtaining a
Method
object that represents the vibrate
method, updating the
button's text if successful.
self.method = cl.getMethod(self.METHOD, array([Long.TYPE]))
self.button.setText("Invoke " + self.METHOD + "(" + str(self.DURATION) + ")")
except NoSuchMethodException, e:
self.button.setEnabled(False)
If either of the methods are not found then we disable the button to prevent the user from clicking it since there is no suitable method to invoke.
Only if the button is enabled can the following method be called. In it, we
invoke the method stored in the method
field with the required arguments:
a long
value supplied as a "boxed" Long
instance.
def onClick(self, view):
try:
self.method.invoke(self.vibrator, array([Long(self.DURATION)]))
except:
pass
The invocation can fail with a variety of exceptions so we simply catch all of them in a single clause.