This question has been asked before here but its answer is incorrect. I would like to rotate some views on screen orientation change, but I want to keep the layout unchanged. They should be rotated 90, 180, 270 or 360 degrees according to the current orientation (SCREEN_ORIENTATION_LANDSCAPE, SCREEN_ORIENTATION_PORTRAIT, SCREEN_ORIENTATION_REVERSE_LANDSCAPE, SCREEN_ORIENTATION_REVERSE_PORTRAIT).
This is what I want to achieve:
The answer in the link I mentioned stated that I should create a new different layout in layout-land. Clearly, this is not what I want. I don't want to recreate the activity or change layout orientation. I only want to rotate some views, and keep other views unchanged on orientation change.
There is a huge difference between rotating specific views and changing or recreating the whole layout (both on orientation change).
Using the answer in this link, I will be able to get the current screen orientation with this method:
public static int getScreenOrientation(Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
int rotation = windowManager.getDefaultDisplay().getRotation();
DisplayMetrics dm = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
int orientation;
// if the device's natural orientation is portrait:
if ((rotation == Surface.ROTATION_0
|| rotation == Surface.ROTATION_180) && height > width ||
(rotation == Surface.ROTATION_90
|| rotation == Surface.ROTATION_270) && width > height) {
switch (rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_90:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_180:
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
case Surface.ROTATION_270:
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
default:
Log.e("ScreenOrientation", "Unknown screen orientation. Defaulting to " + "portrait.");
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
}
}
// if the device's natural orientation is landscape or if the device
// is square:
else {
switch (rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_90:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_180:
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
case Surface.ROTATION_270:
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
default:
Log.e("ScreenOrientation", "Unknown screen orientation. Defaulting to " + "landscape.");
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
}
}
return orientation;
}
On orientation change, I would like to do something simple like this:
RotateAnimation rotateAnimation = new RotateAnimation(0, getScreenOrientation(getContext()));
rotateAnimation.setDuration(2000);
for (int i = 0; i < 63; i++) {
Button button = (Button) rootView.findViewById(i);
button.startAnimation(rotateAnimation);
}
Another way to rephrase my question would be "Is there any way to detect orientation change in onConfigurationChanged() method without changing the layout?". The problem is that it will not be able to detect any orientation change if I already disable layout orientation change.
Anyone knows how it is done? I might have totally gone through wrong steps, and I think I will have to use Accelerometer Sensor or something similar to that to achieve what I want, so please guide me through.
Try to use OrientationEventListener. You don't need to use onConfigurationChanged and android:configChanges="orientation|keyboardHidden|screenSize". You need set android:screenOrientation="portrait" for the activity in AndroidManifest.xml. Here is my solution with OrientationEventListener:
public class MyActivity extends Activity{
private ImageButton menuButton;
private Animation toLandAnim, toPortAnim;
private OrientationListener orientationListener;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_image_ruler);
menuButton=(ImageButton)findViewById(R.id.menu_button);
toLandAnim= AnimationUtils.loadAnimation(this, R.anim.menubutton_to_landscape);
toPortAnim= AnimationUtils.loadAnimation(this, R.anim.menubutton_to_portrait);
orientationListener = new OrientationListener(this);
}
#Override protected void onStart() {
orientationListener.enable();
super.onStart();
}
#Override protected void onStop() {
orientationListener.disable();
super.onStop();
}
private class OrientationListener extends OrientationEventListener{
final int ROTATION_O = 1;
final int ROTATION_90 = 2;
final int ROTATION_180 = 3;
final int ROTATION_270 = 4;
private int rotation = 0;
public OrientationListener(Context context) { super(context); }
#Override public void onOrientationChanged(int orientation) {
if( (orientation < 35 || orientation > 325) && rotation!= ROTATION_O){ // PORTRAIT
rotation = ROTATION_O;
menuButton.startAnimation(toPortAnim);
}
else if( orientation > 145 && orientation < 215 && rotation!=ROTATION_180){ // REVERSE PORTRAIT
rotation = ROTATION_180;
menuButton.startAnimation(toPortAnim);
}
else if(orientation > 55 && orientation < 125 && rotation!=ROTATION_270){ // REVERSE LANDSCAPE
rotation = ROTATION_270;
menuButton.startAnimation(toLandAnim);
}
else if(orientation > 235 && orientation < 305 && rotation!=ROTATION_90){ //LANDSCAPE
rotation = ROTATION_90;
menuButton.startAnimation(toLandAnim);
}
}
}
}
This also prevents from too frequent rotations when orientation is about 45, 135... etc.
Hope it helps.
The basics are actually a lot easier. Have a look at Handling Runtime Changes.
First things first, by setting
android:configChanges="orientation|keyboardHidden|screenSize"
in your Manifest on your activity tag you can handle the orientation change yourself. (orientation should be enough, but there are sometimes issues where the event does not fire with that alone.)
You then skip onCreate and instead onConfigurationChanged gets called. Overwrite this method and apply your layout changes here. Whether you change your linearLayouts orientation here or have a custom view handling layout for different screens itself is up to you and depends on your implementation.
Animating will be a bit trickier, if it is even possilbe. A quick search says it is not.
Update for comment "I only want to rotate some views themselves rather than rotating the layout"
In theory it is possible to create your own layout and handle the drawing of your child views. I just tried it but could not produce any results in an appropriate time, but what you would need to do:
keep your last measured values use tags on the view or similar approaches to keep the last measurements and layouts, so that after the orientation change you can diff
await orientation change: trigger rotated drawing - rotate the canvas, layout the views with the previous dimensions, and draw the child views where they would have been before, and
start an animation interpolate from the last to the new values, rotating the canvas from the last to the new layout
This is how I would do it.
Related
From Multi-Window documentation:
Disabled features in multi-window mode
Certain features are disabled or ignored when a device is in multi-window mode, because they don’t make sense for an activity which may be sharing the device screen with other activities or apps. Such features include:
Some System UI customization options are disabled; for example, apps cannot hide the status bar if they are not running in full-screen mode.
The system ignores changes to the android:screenOrientation attribute.
I get that for most apps it doesn't make sense to distinct between portrait and landscape modes, however I am working on SDK which contains camera view which user can put on any activity they wish - including activity that supports multi-window mode. The problem is that camera view contains SurfaceView/TextureView which displays the camera preview and in order to display preview correctly in all activity orientations, knowledge about correct activity orientation is required so that camera preview can be correctly rotated.
The problem is that my code which calculates correct activity orientation by examining current configuration orientation (portrait or landscape) and current screen rotation. The problem is that in multi-window mode current configuration orientation does not reflect the real activity orientation. This then results with camera preview being rotated by 90 degrees because Android reports different configuration than orientation.
My current workaround is to check for requested activity orientation and use that as a basis, but there are two problems with that:
the requested activity orientation does not have to reflect actual activity orientation (i.e. request may still not be fulfilled)
the requested activity orientation can be 'behind', 'sensor', 'user', etc. which does not reveal any information about current activity orientation.
According to documentation, screen orientation is actually ignored in multi-window mode, so 1. and 2. just won't work
Is there any way to robustly calculate correct activity orientation even in multi-window configuration?
Here is my code that I currently use (see comments for problematic parts):
protected int calculateHostScreenOrientation() {
int hostScreenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
int rotation = getDisplayOrientation(wm);
boolean activityInPortrait;
if ( !isInMultiWindowMode() ) {
activityInPortrait = (mConfigurationOrientation == Configuration.ORIENTATION_PORTRAIT);
} else {
// in multi-window mode configuration orientation can be landscape even if activity is actually in portrait and vice versa
// Try determining from requested orientation (not entirely correct, because the requested orientation does not have to
// be the same as actual orientation (when they differ, this means that OS will soon rotate activity into requested orientation)
// Also not correct because, according to https://developer.android.com/guide/topics/ui/multi-window.html#running this orientation
// is actually ignored.
int requestedOrientation = getHostActivity().getRequestedOrientation();
if ( requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT ||
requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT ||
requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT ) {
activityInPortrait = true;
} else if ( requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE ||
requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE ||
requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE ) {
activityInPortrait = false;
} else {
// what to do when requested orientation is 'behind', 'sensor', 'user', etc. ?!?
activityInPortrait = true; // just guess
}
}
if ( activityInPortrait ) {
Log.d(this, "Activity is in portrait");
if (rotation == Surface.ROTATION_0) {
Log.d(this, "Screen orientation is 0");
hostScreenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
} else if (rotation == Surface.ROTATION_180) {
Log.d(this, "Screen orientation is 180");
hostScreenOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
} else if (rotation == Surface.ROTATION_270) {
Log.d(this, "Screen orientation is 270");
// natural display rotation is landscape (tablet)
hostScreenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
} else {
Log.d(this, "Screen orientation is 90");
// natural display rotation is landscape (tablet)
hostScreenOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
}
} else {
Log.d(this, "Activity is in landscape");
if (rotation == Surface.ROTATION_90) {
Log.d(this, "Screen orientation is 90");
hostScreenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
} else if (rotation == Surface.ROTATION_270) {
Log.d(this, "Screen orientation is 270");
hostScreenOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
} else if (rotation == Surface.ROTATION_0) {
Log.d(this, "Screen orientation is 0");
// natural display rotation is landscape (tablet)
hostScreenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
} else {
Log.d(this, "Screen orientation is 180");
// natural display rotation is landscape (tablet)
hostScreenOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
}
}
return hostScreenOrientation;
}
private int getDisplayOrientation(WindowManager wm) {
if (DeviceManager.getSdkVersion() < 8) {
return wm.getDefaultDisplay().getOrientation();
}
return wm.getDefaultDisplay().getRotation();
}
private boolean isInMultiWindowMode() {
return Build.VERSION.SDK_INT >= 24 && getHostActivity().isInMultiWindowMode();
}
protected Activity getHostActivity() {
Context context = getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity) context;
}
context = ((ContextWrapper) context).getBaseContext();
}
return null;
}
EDIT: I've reported this also to Android issue tracker.
I don’t know if this should be considered a solution or just a workaround.
As you say, your problems come with Android N and its multi-window mode. When the app is in multi window, your Activity is not tied to the full display dimensions. This redefines the concept of Activity orientation. Quoting Ian Lake:
Turns out: “portrait” really just means the height is greater than the
width and “landscape” means the width is greater than the height. So
it certainly makes sense, with that definition in mind, that your app
could transition from one to the other while being resized.
So there is no link anymore between Activity orientation changing and device physically being rotated. (I think the only reasonable use of Activity orientation changes now is to update your resources.)
Since you are interested in device dimensions, just get its DisplayMetrics. Quoting docs,
If requested from non-Activity context
metrics will report the size of the entire display based on current
rotation and with subtracted system decoration areas.
So the solution is:
final Context app = context.getApplicationContext();
WindowManager manager = (WindowManager) app.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
int width = metrics.widthPixels;
int height = metrics.heightPixels;
boolean portrait = height >= width;
Width and height values will be swapped (more or less) when the device is tilted.
If this works, I would personally run it every time, deleting the isInMultiWindowMode() branch, because
it’s not expensive
our assumptions stand also in the non-multi-window mode
it will presumably work well with any other future kinds of modes
you avoid the race condition of isInMultiWindowMode() described by CommonsWare
I thought you could utilise the accelerometer to detect where's "down" - and thus the orientation of the phone. The Engineer Guy explains that that's the way the phone itself does it.
I searched here on SO for a way to do that and found this answer. Basically you need to check which of the 3 accelerometers detect the most significant component of the gravitational pull, which you know is roughly 9.8m/s² near the ground of the earth. Here's the code snippet from it:
private boolean isLandscape;
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(
Sensor.TYPE_ACCELEROMETER),1000000);
private final SensorEventListener mSensorListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent mSensorEvent) {
float X_Axis = mSensorEvent.values[0];
float Y_Axis = mSensorEvent.values[1];
if((X_Axis <= 6 && X_Axis >= -6) && Y_Axis > 5){
isLandscape = false;
}
else if(X_Axis >= 6 || X_Axis <= -6){
isLandscape = true;
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
Be careful as this code might not work in every situation, as you need to take into account scenarios like being on a stopping/accelerating train or moving the phone fast in a game - here's the orders of magnitude page on wiki to get you started. It looks like you're safe with the values Khalil put in his code (in his answer), but I would take extra caution and research into what values might be generated in the different scenarios.
It's not a flawless idea, but I think as long as the API is built the way it is - whithout allowing you to get their calculated orientation - I think it's a beneficial workaround.
Is it possible to load different xml layouts based on its current orientation instead of just by portrait/landscape?
I am writing an app with a front-facing camera feature.
When the device is rotated 180 degrees, my CAPTURE button is now right beside the camera. This causes the camera to be blocked by my fingers when i try to click the CAPTURE button.
In my landscape XML, the button is always to the right. I like to align it towards the home button (away from the front camera).
If it cannot be done via XML, is there another way to achieve this?
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<SurfaceView
android:id="#+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageButton
android:id="#+id/image_capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_margin="24dp"
android:background="#drawable/rounded_button_primary"
android:padding="28dp"
android:src="#drawable/ic_camera_black_48dp"
android:tint="#color/icons" />
</RelativeLayout>
yes, you can design a xml file with same name separately for landscape view, create a folder with name layout-land and place the xml there.
android will automatically reload the xml
or
you can set gravity by overriding onConfigurationChanged method like this
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}`
Edit:
private int getScreenOrientation() {
int rotation = getWindowManager().getDefaultDisplay().getRotation();
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
int orientation;
// if the device's natural orientation is portrait:
if ((rotation == Surface.ROTATION_0
|| rotation == Surface.ROTATION_180) && height > width ||
(rotation == Surface.ROTATION_90
|| rotation == Surface.ROTATION_270) && width > height) {
switch(rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_90:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_180:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
case Surface.ROTATION_270:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
default:
Log.e(TAG, "Unknown screen orientation. Defaulting to " +
"portrait.");
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
}
}
return orientation;
}
I am working on a custom camera Android app. It works fine with the preview screen fits nicely with the screen size on both portrait and landscape modes. However, when changing phone orientation, there is a noticeable delay in preview redraw. Searching through the forums I came across others seeing similar issues when dealing with phone orientation change. Following some suggestion to avoid activity being destroyed and recreated, and camera being released and opened during such a change, I have added the following line to the AndroidManifest.xml:
android:configChanges="orientation|screenSize">
From some debugging and testing, I can confirm that the activity is no longer being destroyed/created on orientation change. However, even with this addition, there is a noticeable delay when the preview redraws going from portrait to landscape, vice versa. Here is the code for onConfigurationChanged method within the Activity class:
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mPreview.setCameraDisplayOrientation(this, 1, mCamera);
}
And within the SurfaceView class:
public void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
camera.setDisplayOrientation(result);
}
And within surfaceChanged, I have:
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
initialisePreview(w, h); // gets best preview size and sets camera parameters
mCamera.startPreview();
}
There is nothing new about the above setCameraDisplayOrientation method and was adapted from Android Developer website. I am not sure what else could be contributing to such a delay with redraw. If anyone has any thoughts, please advise. Thank you.
Instead of handling screen orientation change as described above, I resorted to making Activity ignore orientation changes determined by orientation sensor during onCreate() using:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
With this change, the preview continues on seamlessly when the phone orientation changes. This sppears counter intuitive, but it resolved my issue. Hope it helps someone.
You would think that there would be a straight forward solution. The Android docs state:
The orientation sensor was deprecated in Android 2.2 (API level 8).
Instead of using raw data from the orientation sensor, we recommend
that you use the getRotationMatrix() method in conjunction with the
getOrientation() method to compute orientation values.
Yet, they don't provide a solution on how to implement getOrientation() and getRotationMatrix(). I've spent several hours reading through posts here on developers using these methods but they all have partially pasted code or some weird implementation. Googling hasn't provided a tutorial. Can someone please paste a simple solution using these two methods to generate the orientation??
Here is the implementation for getOrientation():
public int getscrOrientation()
{
Display getOrient = getWindowManager().getDefaultDisplay();
int orientation = getOrient.getOrientation();
// Sometimes you may get undefined orientation Value is 0
// simple logic solves the problem compare the screen
// X,Y Co-ordinates and determine the Orientation in such cases
if(orientation==Configuration.ORIENTATION_UNDEFINED){
Configuration config = getResources().getConfiguration();
orientation = config.orientation;
if(orientation==Configuration.ORIENTATION_UNDEFINED){
//if height and widht of screen are equal then
// it is square orientation
if(getOrient.getWidth()==getOrient.getHeight()){
orientation = Configuration.ORIENTATION_SQUARE;
}else{ //if widht is less than height than it is portrait
if(getOrient.getWidth() < getOrient.getHeight()){
orientation = Configuration.ORIENTATION_PORTRAIT;
}else{ // if it is not any of the above it will definitely be landscape
orientation = Configuration.ORIENTATION_LANDSCAPE;
}
}
}
}
return orientation; // return value 1 is portrait and 2 is Landscape Mode
}
And you can also refer this example which represent the use of both the methods:
getOrientation and getRotationMatrix
http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html
public int getScreenOrientation() {
// Query what the orientation currently really is.
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
return 1; // Portrait Mode
}else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
return 2; // Landscape mode
}
return 0;
}
protected void onResume() {
// change the screen orientation
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setContentView(R.layout.portrait);
} else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.landscape);
} else {
setContentView(R.layout.oops);
}
}
For example, I started application then device is turned 90 degree by side.I want to detect this event for each planes on device.
You can get the screen orientation (for example in your onResume() Method) like this:
private static final int ORIENTATION_0 = 0;
private static final int ORIENTATION_90 = 3;
private static final int ORIENTATION_270 = 1;
Display display = ((WindowManager)
getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int screenOrientation = display.getRotation();
switch (screenOrientation)
{
default:
case ORIENTATION_0: // Portrait
// do smth.
break;
case ORIENTATION_90: // Landscape right
// do smth.
break;
case ORIENTATION_270: // Landscape left
// do smth.
break;
}
Use SensorManager and TYPE_GYROSCOPE/TYPE_ROTATION_VECTOR/TYPE_ORIENTATION/ to get these value.
Look this page for details.
I think you have to use the sensor manager to calculate x,y,z on every point. and use equation to find angle between two points. consider your starting points (0,0,0);
You can use OrientationEventListener for the planes
OrientationEventListener mOrientationListener = new OrientationEventListener(
getApplicationContext()) {
#Override
public void onOrientationChanged(int orientation) {
}
};
if (mOrientationListener.canDetectOrientation()) {
mOrientationListener.enable();
}