Development for the plugin is nearly complete. All that’s left is the Android implementation!
Prerequisite: Familiarize yourself with the Capacitor Custom Native Android Code documentation before continuing.
Open up the Capacitor application’s Android project in Android Studio by running
npx cap open android
. Expand the app module and the java folder and right-click on your app’s Java package. Select
New -> Package from the context menu and create a subpackage named
plugins. Right-click the
plugins package and repeat the preceding process to create a subpackage named
ScreenOrientation.
Next, right-click the ScreenOrientation package and add a new Java file by selecting
New -> Java File from the context menu. Name this file
ScreenOrientationPlugin.java
. Repeat the process to create a new file named
ScreenOrientation.java
.
Copy the following code into
ScreenOrientationPlugin.java
:
package io.ionic.cap.plugin.plugins.ScreenOrientation;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;
@CapacitorPlugin(name = "ScreenOrientation")
public class ScreenOrientationPlugin extends Plugin {
@PluginMethod()
public void orientation(PluginCall call) {
call.resolve();
}
@PluginMethod()
public void lock(PluginCall call) {
call.resolve();
}
@PluginMethod()
public void unlock(PluginCall call) {
call.resolve();
}
}
Register the plugin class within the project’s MainActivity to bridge between Java and JavaScript. Open
MainActivity.java
and add an
onCreate()
method where we can register the plugin:
package io.ionic.cap.plugin;
import android.os.Bundle;
import com.getcapacitor.BridgeActivity;
import io.ionic.cap.plugin.plugins.ScreenOrientation.ScreenOrientationPlugin;
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerPlugin(ScreenOrientationPlugin.class);
}
}
Like iOS, we will tackle getting the current screen orientation first. Open
ScreenOrientation.java
to set up the class and write a method to get the current orientation:
package io.ionic.cap.plugin.plugins.ScreenOrientation;
import android.view.Surface;
import androidx.appcompat.app.AppCompatActivity;
public class ScreenOrientation {
private AppCompatActivity activity;
public ScreenOrientation(AppCompatActivity activity) {
this.activity = activity;
}
public String getCurrentOrientationType() {
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
return fromRotationToOrientationType(rotation);
}
private String fromRotationToOrientationType(int rotation) {
switch (rotation) {
case Surface.ROTATION_90:
return "landscape-primary";
case Surface.ROTATION_180:
return "portrait-secondary";
case Surface.ROTATION_270:
return "landscape-secondary";
default:
return "portrait-primary";
}
}
}
Next, wire up the
orientation
method in
ScreenOrientationPlugin.java
to call the implementation class’s method:
package io.ionic.cap.plugins.ScreenOrientation;
import com.getcapacitor.JSObject;
/* Remaining imports omitted for brevity */
@CapacitorPlugin(name = "ScreenOrientation")
public class ScreenOrientationPlugin extends Plugin {
private ScreenOrientation implementation;
@Override
public void load() {
implementation = new ScreenOrientation(getActivity());
}
@PluginMethod()
public void orientation(PluginCall call) {
JSObject ret = new JSObject();
String type = implementation.getCurrentOrientationType();
ret.put("type", type);
call.resolve(ret);
}
/* Remaining code omitted for brevity */
}
The
load()
method is the proper place to initialize the
ScreenOrientation
class instance with the Capacitor bridge object.
Run the app from within Android Studio, either on an actual device or an Android emulator. Open Logcat and you should see the call logged:
V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 89582874, pluginId: ScreenOrientation, methodName: orientation
Note: The exact value of the logs will be different for you. In this example,
89582874
is an arbitrary ID assigned to the method call made from the plugin.
Android considers the rotation of a device a runtime configuration change, so we need a way for our plugin to handle configuration changes.
Capacitor provides an overridable method,
handleOnConfigurationChanged()
, that can be used to respond to runtime configuration changes.
First add the following import to the
ScreenOrientationPlugin
class:
import android.content.res.Configuration;
Then add the following methods to the
ScreenOrientationPlugin
class:
@Override
public void handleOnConfigurationChanged(Configuration newConfig) {
super.handleOnConfigurationChanged(newConfig);
this.onOrientationChanged();
}
private void onOrientationChanged() {
JSObject ret = new JSObject();
String type = implementation.getCurrentOrientationType();
ret.put("type", type);
notifyListeners("screenOrientationChange", ret);
}
When Android notifies an application of a configuration change, it returns the entire new configuration object, presenting two challenges:
We will need the plugin to keep track of the previous
newConfig.orientation
value to compare against additional configuration changes to address those challenges.
Make the following additions to the
ScreenOrientation
class:
@Nullable private int configOrientation;
public boolean hasOrientationChanged(int orientation) {
if (orientation == configOrientation) {
return false;
} else {
this.configOrientation = orientation;
return true;
}
}
Don’t forget to import
androidx.annotation.Nullable
to
ScreenOrientation.java
.
Then update the
handleOnConfigurationChanged()
method in
ScreenOrientationPlugin.java
:
@Override
public void handleOnConfigurationChanged(Configuration newConfig) {
super.handleOnConfigurationChanged(newConfig);
if(implementation.hasOrientationChanged(newConfig.orientation)) {
this.onOrientationChanged();
}
}
Now, the plugin will only notify listeners if-and-only-if runtime configuration changes pertain to the orientation changing.
As we saw with the iOS implementation, we’ll need a helper method to map the JavaScript OrientationType into a corresponding native enumeration value. For Android, we’ll map an OrientationType to an ActivityInfo enumeration value. Add the following method to the
ScreenOrientation
class:
private int fromOrientationTypeToEnum(String orientationType) {
switch (orientationType) {
case "landscape-primary":
return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
case "landscape-secondary":
return ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
case "portrait-secondary":
return ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
default:
// Case: portrait-primary
return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
}
}
Make sure to import
android.content.pm.ActivityInfo
to
ScreenOrientation.java
.
Next, add a
lock()
method to the
ScreenOrientation
class:
public void lock(String orientationType) {
int orientationEnum = fromOrientationTypeToEnum(orientationType);
activity.setRequestedOrientation(orientationEnum);
}
This method needs to get called from the ScreenOrientationPlugin
class:
@PluginMethod()
public void lock(PluginCall call) {
String orientationType = call.getString("orientation");
if(orientationType == null) {
call.reject("Input option 'orientation' must be provided.");
return;
}
implementation.lock(orientationType);
call.resolve();
}
Note, we guard against calls to the
lock()
method that do not supply the
orientation
input parameter.
To unlock the screen orientation, we set the activity’s orientation type to the unspecified enumeration value. Add the following method to the
ScreenOrientation
class:
public void unlock() {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
Then call the implementation method from the ScreenOrientationPlugin
class:
@PluginMethod()
public void unlock(PluginCall call) {
implementation.unlock();
call.resolve();
}
In Android Studio, run the app on either a device or an emulator. Pressing the “Rotate My Device” button will rotate the screen orientation into landscape mode, and if you rotate further, you will see that the screen orientation is locked. Pressing “Confirm Signature“ will unlock the screen orientation.
Note: Ensure that you have the Auto-rotate device setting set to on before testing the plugin out; otherwise, it won’t function.
Congratulations, you’ve built a Capacitor plugin that works for web, iOS, and Android! 👏 👏 👏
As it stands, the
ScreenOrientation
plugin is a local plugin; only this application can use it. And that’s OK! Many times you’ll only want a plugin used only within a particular app. However, if you would like to reuse a plugin in multiple apps, we’ll see how to do that in the final step: packaging the plugin.