Toggle Flashlight in Camera2 without Interrupting Preview - Java for Android App Development

Just started using the Camera2 framework because of the increased control it provides over the low-level functions of the camera. However, I am having some trouble turning the flashlight on and off quickly. With the old Camera API, I could toggle flash while supplying a preview by:
Code:
try
{
android.hardware.Camera.Parameters parameters = c.getParameters();
if (parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_OFF))
{
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
Log.i("HeartBeatAlgorithm", "LightOn");
}
else if (parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_TORCH))
{
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
Log.i("HeartBeatAlgorithm", "LightOff");
}
c.setParameters(parameters);
}
catch (Exception exception)
{
c.release();
c = null;
}
And the flashlight would quickly turn on or off, without any noticeable interrupt. With Camera2, however, it seems as though flash mode is a property of the CaptureSession, meaning an entirely new CaptureSession needs to be created to change flash mode, i.e.:
Code:
try
{
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface surface = new Surface(texture);
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
if (mLightNowOn == true)
{
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
}
else
{
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
}
mPreviewRequestBuilder.addTarget(surface);
mPreviewRequest = mPreviewRequestBuilder.build();
mCameraDevice.createCaptureSession(Arrays.asList(surface), mSessionStateCallback, null);
}
catch (CameraAccessException e)
{
e.printStackTrace();
}
As is mentioned in the developer docs, "Creating a session is an expensive operation and can take several hundred milliseconds, since it requires configuring the camera device's internal pipelines and allocating memory buffers for sending images to the desired targets." It definitely does, and there is a noticeable delay in my app when toggling flash mode.
I really need to be able to quickly toggle flash modes without interrupting the preview so much. Is there any way around this, or is it unavoidable due to the new API pipeline?

Related

Direct X and PNG Transparency on WM6.1 with .Net CF3.5

Hi all,
I'm trying to have transparent PNGs on my screen.
What is the best way to doing this ? I'm in C#, I tried DirectX, but it doesn't work.
What am I doing wrong ?
My code :
Code:
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.WindowsMobile.DirectX;
using Microsoft.WindowsMobile.DirectX.Direct3D;
using System.Runtime.InteropServices;
namespace Microsoft.Samples.MD3DM
{
// The main class for this sample
public class SimpleSMS : Form
{
// Our global variables for this project
Device device = null;
Texture texture = null;
Sprite sprite = null;
Rectangle rect;
public SimpleSMS()
{
// Set the caption
this.Text = "SimpleSMS";
this.MinimizeBox = false;
}
// Prepare the rendering device
public bool InitializeGraphics()
{
try
{
// Now let's setup our D3D parameters
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
device = new Device(0, DeviceType.Default, this, CreateFlags.None, presentParams);
this.OnCreateDevice(device, null);
}
catch (DirectXException)
{
return false;
}
return true;
}
void OnCreateDevice(object sender, EventArgs e)
{
texture = TextureLoader.FromFile(device, @"badge.png");
sprite = new Sprite(device);
rect = new Rectangle(0, 0, 48, 48);
}
// All rendering for each frame occurs here
private void Render()
{
if (device != null)
{
device.Clear(ClearFlags.Target, System.Drawing.Color.Black, 1.0f, 0);
//Begin the scene
device.BeginScene();
device.RenderState.SourceBlend = Blend.SourceAlpha;
device.RenderState.DestinationBlend = Blend.InvSourceAlpha;
device.RenderState.AlphaBlendEnable = true;
sprite.Begin(SpriteFlags.AlphaBlend);
sprite.Draw(texture, rect, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(100.0f, 100.0f, 0.0f), Color.White.ToArgb());
sprite.End();
//End the scene
device.EndScene();
device.Present();
}
}
// Called to repaint the window
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
// Render on painting
this.Render();
// Render again
this.Invalidate();
}
// Called to repaint the window background
protected override void OnPaintBackground(
System.Windows.Forms.PaintEventArgs e)
{
// Do nothing to ensure that the rendering area is not overdrawn
}
// Close the window when Esc is pressed
protected override void OnKeyPress(
System.Windows.Forms.KeyPressEventArgs e)
{
// Esc was pressed
if ((int)(byte)e.KeyChar == (int)System.Windows.Forms.Keys.Escape)
this.Close();
}
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
SimpleSMS frm = new SimpleSMS();
// Initialize Direct3D
if (!frm.InitializeGraphics())
{
MessageBox.Show("Could not initialize Direct3D. " +
"This tutorial will exit.");
return;
}
Application.Run(frm);
}
}
}
Thanks for answers,
Scuse my bad english :-/
Not sure this helps, but RLTODAY works very well with transparent pngs in any WM version, and recently he released the source code:
http://rotlaus-software.de/forum/index.php?topic=1847.0
You can use ImagingFactory in OpenNETCF or other wrapper over the internet. PNGs with alpha work work for me.
AlphaControls
There is a project on Codeplex that can help you with transparency called AlphaControls. Also have a look on codeproject at the iPhone app clone
moneytoo said:
You can use ImagingFactory in OpenNETCF or other wrapper over the internet. PNGs with alpha work work for me.
Click to expand...
Click to collapse
Thank you all for answers ...
I tried OpenNetCF, without any result.
Do you have a piece of code in example ?
Try this:
http://www.codeplex.com/alphamobilecontrols
Or this:
http://johan.andersson.net/blog/2007/10/solution-for-transparent-images-on.html

Application Request for Weight Watchers Points Calculator

Can someone make a .cab or an .exe program to calculate Weight Watchers points? I found this article on the internet where it looks like someone as already done it but they did not post it. Here is the article
http://geekswithblogs.net/cdahlinge...-mobile-meets-weight-watchers--mvp-style.aspx
Craig Dahlinger
<< Presenting at Richdmond code camp 2008.2 | Home | mshtml – the ongoing adventure >> windows mobile meets weight watchers : MVP style Ok, so I know it has been a long time since a post, but it has been really busy with work and family. I have been busy coding and learning lots of new stuff. I work with a great bunch of developers and my current team lead is a great mentor.
Well for the new year the wife and I decided to get back into shape. I started hitting the gym and so did she but she is also doing weight watchers with a friend. One of the things they do is they have to calculate points on a daily basis. These points are comprised of calories, fat and fiber. There is a formula for these three which in turn results in the number of points a particular item is. A few months ago I convinced the wife to get a windows mobile device (woo hoo!) and she is a good power user. So one night she asks me, β€œIs there a way I can just enter in the calories, fat and fiber on my phone and it tell me how many points something is?”. I did some searching and there are numerous online versions of the calculator but no native ones for windows mobile. I found the formula here, and started to get to work.
I wanted to approach this application using the MVP design pattern. I know it may be overkill for this simple of an application but I thought it would be good practice.
I started with the interface for the data model, in this case it would be the main caloric properties of food.
namespace WWPC.Common.Interfaces{ public interface IFoodModel { int Fiber { get; set; } int Calories { get; set; } float Fat { get; set; } int Points { get; set; } int CalculatePoints(); }}I then wrote up the interface for the view for the model.
namespace WWPC.Common.Interfaces{ public interface IFoodCalcView { int Calories { get; } int Fiber { get; } float Fat { get; } int Points { set; } event EventHandler DataChanged; }}Next, came the interface for the presenter.
public interface IFoodCalcPresenter { void OnCalculatePoints(); }
Ok, now that I got my main interfaces in place, time to code up the implementation. I started with the model first since this was the class that would provide the implementation for calculating the caloric points. Using the formula mentioned above, the CalculatePoints() method came out like so:
public int CalculatePoints(){ var calories = Convert.ToDecimal(Calories); var cal = calories / 50; var totalFat = Convert.ToDecimal(Fat); var fat = totalFat / 12; var fiber = Convert.ToDecimal(Fiber); return Points = Convert.ToInt32(Math.Round(cal + fat - (fiber/5), 0)); } With the model complete, I then moved to the presenter. The presenter would be responsible for binding the model to the view responding to the data changes in the view and rebinding those changes to the model. I made the presenter with an overloaded constructor to take a view and a model. The presenter then binds to the data changed event on the view which enables the presenter to update the model from the view. The OnCalculatePoints() method will update the view with the points value after using the model for calculation.
namespace WWPC.Common{ public class FoodPresenter : IFoodCalcPresenter { private readonly IFoodCalcView _View; private readonly IFoodModel _Model; public FoodPresenter(IFoodCalcView view, IFoodModel model) { _View = view; _View.DataChanged += new EventHandler(_View_DataChanged); _Model = model; } void _View_DataChanged(object sender, EventArgs e) { SetModelFromView(); } private void SetModelFromView() { _Model.Calories = _View.Calories; _Model.Fat = _View.Fat; _Model.Fiber = _View.Fiber; } #region IFoodCalcPresenter Members public void OnCalculatePoints() { _View.Points = _Model.CalculatePoints(); } #endregion }}
With the presenter done it was time to implement the view. I wanted a simple mobile form where you can enter in data quickly and then calculate the results. I initially tried using a label to display the result, but did not like it. I then tried a mobile gauge control, but that took up too much space on the small screen. Finally I decided to use the notification class for windows mobile. I did not use the managed wrapper version, I used the the version created by Christopher Fairbairn, found here. This version has an awesome implementation which exposes many features of the notification class. I wanted to give the user the ability to dismiss the notification when they were done reading the results. Also using the notification class the UI was able show the needed text boxes for entry and the SIP panel along with the results without needing to scroll the screen. Here is a screen shot of the main form.
Now with the controls in place on the form, I can implement the view. The form creates a new presenter and passed into it a new model during construction. When the calculate menu option is clicked the main form raises the data changed event then calls the OnCalculateMethod on the presenter. When the presenter binds the model to the view, during the set of the points value, the notification is shown to the user via the ShowNotification method.
namespace WWPC.Calc{ public partial class WWPCalculator : Form, IFoodCalcView { private readonly FoodPresenter _Presenter; private NotificationWithSoftKeys _Notification; public WWPCalculator() { InitializeComponent(); _Presenter = new FoodPresenter(this,new FoodModel()); } public int Calories { get { return (string.IsNullOrEmpty(txtCalories.Text)) ? 0 : Int32.Parse(txtCalories.Text); } } public int Fiber { get { return (cmbFiber.Text == "4 or more") ? 4 : (string.IsNullOrEmpty(cmbFiber.Text)) ? 0 :Int32.Parse(cmbFiber.Text); } } public float Fat { get { return (string.IsNullOrEmpty(txtFat.Text)) ? 0 : float.Parse(txtFat.Text); } } public int Points { set { ShowPointsNotification(value); } } public event EventHandler DataChanged; private void mnuExit_Click(object sender, EventArgs e) { this.Close(); } private void mnuCalculate_Click(object sender, EventArgs e) { if (DataChanged != null) this.DataChanged(sender, e); _Presenter.OnCalculatePoints(); } private void mnuClear_Click(object sender, EventArgs e) { txtCalories.Text = string.Empty; txtFat.Text = string.Empty; cmbFiber.Text = "0"; } private void ShowPointsNotification(int points) { _Notification = new NotificationWithSoftKeys { Text = String.Format("Total Points:{0}", points), Caption = "Weight Watchers Point Calculator", RightSoftKey = new NotificationSoftKey(SoftKeyType.Dismiss, "Dismiss"), }; _Notification.RightSoftKeyClick+=new EventHandler(_Notification_RightSoftKeyClick); _Notification.Visible = true; } void _Notification_RightSoftKeyClick(object sender, EventArgs e) { if (_Notification == null) return; _Notification.Visible = false; _Notification = null; } }}
Now, when it is all put together, it looks like so.
Below is a link to the source code. The project was done using Visual Studio 2008 against the windows mobile 5 sdk. It will also work against windows mobile 6 sdk, I just chose version 5 since that is the common sdk. Thanks for reading!!

[Q] Looking for library app to crop and load images

I'm currently developing an app and from within the app I'd like to let the user select custom images to use.
Right now I use
Code:
public final int GOT_IMAGE =1;
private void getImage() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
mUri = Uri.fromFile(new
File(Environment.getExternalStorageDirectory(),"temp_image" +
".jpg"));
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mUri);
try {
intent.putExtra("return-data", true);
startActivityForResult(intent,GOT_IMAGE );
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
}
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (resultCode != RESULT_OK) {
customImgChk.setChecked(false);
return;
}
if (requestCode == GOT_IMAGE) {
Bitmap image = BitmapFactory.decodeFile(mUri.getPath());
if (image!=null)
{
image = WPUtil.resizeBitmap(image, WPUtil.IMAGE_SIZE_X,
WPUtil.IMAGE_SIZE_Y);
}
else
{
customImgChk.setChecked(false);
Toast.makeText(this.getApplicationContext(), "Failed to grab
image!", Toast.LENGTH_LONG).show();
}
}
}
This works great on a few devices but not all. I'd really like to come up with a universal way to perform this function but I have not found a way to do it yet.
I've thought about writing up my own image selector and cropper but I'd rather not re-invent the wheel.
Can anybody suggest a decent app/library that I can use to select and or crop photos from within my app?
ImageJ is great. It is a stand alone app but there are published apis for integrating into your own apps.
*its better than that, its open source and you can use the jar and just ignore the gui library
Might look into that
http://rsbweb.nih.gov/ij/
From something awesome

Android camera device and opengl texture glitches

I've been working on adding a view from camera in LibGDX application for Android. I followed this tutorial: code.google.com/p/libgdx/wiki/DeviceCameraIntegration
The view from camera is working properly on every device we've tested, but on some of them (it may depend on the Android version) there's a problem with textures. Instead of transparent backround, grey backround is displayed (on some phones however, there's a black border instead of grey background).
I've realized that this bug is caused by changing format from SurfaceView to translucent:
Code:
SurfaceView glView = (SurfaceView) graphics.getView();
glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
I've decided to change format to translucent only in this part of app, which displays a view from camera - and after turning it off, it goes back to standard opaque format. However this causes other problems: switching to translucent and turning camera on works, but going back to menu and switching displaying to opaque results only with a black screen (application code is executing, I can hear the music but the app doesn't react on input. By trial and error it turned out that on some of devices, for the reason unknown to me, the same code works properly:
Code:
public void setSurfaceFormatToTranslucent() {
try {
if ((this.graphics.getView() instanceof SurfaceView)) {
SurfaceView glView = ((SurfaceView)this.graphics.getView());
glView.setKeepScreenOn(false); //** These two lines I add only during changing to tanslucent
glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
glView.setKeepScreenOn(true); //**
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void setSurfaceFormatToOpaque() {
try {
if ((this.graphics.getView() instanceof SurfaceView)) {
SurfaceView glView = ((SurfaceView)this.graphics.getView());
glView.getHolder().setFormat(PixelFormat.OPAQUE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
However on some of devices this still causes bugs similar to those mentioned above.
Does anyone know what's the problem and how to change SurfaceView format properly while the application is running?

Pseudo-3D effect with gyroscope

I want to share some codes of a small effect that I implemented in my Android app called Arithmetic Puzzles. This is also a chance for me to listen to other people and make improvements. At the end of this post there is a link to the app so that you can see the code in action.
It is a pseudo-3D effect of the playing board items which are looking like rotating slightly based on your viewing angle when you move the device. The effect is not something of very visible but this small non-disturbing animations usually please the user and make the app look cooler.
Why I call it "pseudo"? Because there is no 3D animation behind, and not even a View animation like rotation around some axis or so. The solution is really simple - I just change the border of the item on gyroscope events which somehow fakes the viewing angle change.
The board item is a simple round rectangle and its border is drawn with a gradient of white color going to transparent. This creates the "fake viewing angle" effect.
So here is our BoardItemView class which is just a simple View:
Code:
public class BoardItemView extends View {
// the color of the board itself (blue)
private int mBoardBack;
// the color of the border (white)
private int mBorderColor;
// the color of the gradient end (transparent)
private int mGradientEndColor;
// constructors
public ToolboxItemView(Context context) {
super(context);
init(context);
}
public ToolboxItemView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
// initialize the colors
Resources r = context.getResources();
mBorderColor = r.getColor(R.color.item_border);
mBoardBack = r.getColor(R.color.item_background);
int transparent = r.getColor(android.R.color.transparent);
setBackgroundColor(transparent);
mGradientEndColor = transparent;
}
As you see, there is nothing special about its initialization. I skipped the other member variables so that it doesn't have any info that is not yet needed for understanding, I will add them later.
Let's go to the onDraw() function:
Code:
...
private static final float RECT_PADDING_PERCENTAGE = 0.05f;
private static final float RECT_RADIUS_PERCENTAGE = 0.1f;
private RectF mRoundRect = new RectF();
private Rect mBounds = new Rect();
private float mRadius = 0.0f;
...
@Override
protected void onDraw(Canvas canvas) {
// step 1: collect information needed for drawing
canvas.getClipBounds(mBounds);
float padding = mBounds.height() * RECT_PADDING_PERCENTAGE;
mRoundRect.set(mBounds);
mRoundRect.inset(padding, padding);
mRadius = RECT_RADIUS_PERCENTAGE * mBounds.height();
...
In the first lines of onDraw() I am taking the clip bounds with getClipBounds() function - I need it to understand where I should do my drawing. My experience showed that it is a good idea to get clip bounds, usually you draw between (0, 0) and (width, height), but I have seen some ugly cases (when I was dealing with Android's Launcher codes) where this is not true.
Then I calculate the round rect parameters, like size and corner radius. As you noticed, no "new" calls in onDraw(), all the needed variables are kept as data members and created when this View is instantiated.
Next comes the drawing of the board itself, nothing special:
Code:
...
private Paint mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
...
@Override
protected void onDraw(Canvas canvas) {
...
// step 2: draw the background fill
mRectPaint.setShader(null);
mRectPaint.setDither(false);
mRectPaint.setStyle(Paint.Style.FILL);
mRectPaint.setColor(mBoardBack);
canvas.drawRoundRect(mRoundRect, mRadius, mRadius, mRectPaint);
...
As you can see, I am just drawing a board item as a round rectangle. Before drawing I am setting up the Paint: setting shader to null, dither to false, style to FILL and color to mBoardBack (blue). I will explain the shader and dither in the next step where they are being set. Here I just need to reset (disable) them back. Style is set to FILL so that any shape I paint is also filled with the color of the Paint.
Let's go to the border part, which is interesting:
Code:
...
private LinearGradient mBorderGradient;
...
@Override
protected void onDraw(Canvas canvas) {
...
// step 3: draw the background border
mRectPaint.setStyle(Paint.Style.STROKE);
mRectPaint.setColor(mBorderColor);
createGradient();
mRectPaint.setDither(true);
mRectPaint.setShader(mBorderGradient);
canvas.drawRoundRect(mRoundRect, mRadius, mRadius, mRectPaint);
// step 4: draw the content of a board item here, like text, image, etc...
}
First of all, I am setting the paint style to STROKE. This means that any shape I draw will not be filled with the color, only the border will be drawn. There is also FILL_AND_STROKE style which both draws the border of the shape and fills it with the paint (remember that in previous step we just filled the round rectangle). Since I am not setting the width of the border stroking it will be just one pixel wide. This is enough to see the effect and not big enough for eyes to see the "pseudo"-ness of the 3D effect.
After that I am setting the color of the Paint and then calling a createGradient() function. We will come to that function in a few minutes. Then I am enabling the dither mode on the Paint and setting a shader on it to be the gradient that I just created with that createGradient() function call.
What does all that mean and what is a Shader in Android's Paint system? Its basically quite simple - a Shader is an object from where the Paint gets color information during drawing any shape (except drawing bitmaps). When the shader is null then the Paint object uses the color it was set, otherwise it asks the Shader object what color to use when painting a pixel at some coordinate. As an example you can see a picture acting as a shader and what will happen if a Paint will draw letter 'R' using that shader.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Seems like there are fixed number of shaders in Android, although BitmapShader is covering almost all of the possibilities. In my case I use LinearGradient class which extends Shader class.
TO BE CONTINUED in the thread, seems there is limit on post size...
...CONTINUATION of the original post.
We also set dither to 'true'. It is always a good idea to set dither to true when you are drawing gradients. For more information you can go here where this famous Android Guy is showing some examples of dithering.
Lets go to the createGradient() function:
Code:
...
private Float mXAngle = null;
private Float mYAngle = null;
...
private void createGradient() {
if (mBounds.height() == 0) {
return;
}
int startColor = mBorderColor;
float x0 = mBounds.left;
float y0 = mBounds.bottom;
float x1 = mBounds.right;
float y1 = mBounds.top;
if (mXAngle != null && mYAngle != null) {
if (mXAngle == 0 && mYAngle == 0) {
startColor = mGradientEndColor;
} else {
float h = mBounds.height();
float w = mBounds.width();
float radius = (float) Math.sqrt(h * h + w * w) / 2.0f;
float norm = radius / (float) Math.sqrt(mXAngle * mXAngle + mYAngle * mYAngle);
x0 = mBounds.centerX() + mXAngle * norm;
y0 = mBounds.centerY() + mYAngle * norm;
x1 = mBounds.centerX() - mXAngle * norm;
y1 = mBounds.centerY() - mYAngle * norm;
}
}
mBorderGradient = new LinearGradient(x0, y0, x1, y1,
startColor, mGradientEndColor, Shader.TileMode.CLAMP);
}
The variables mXAngle and mYAngle are set from outside using gyroscope data. We will come to that later. Now think of them as of a vector - they are showing a direction. We are using this direction as a direction of our gradient.
In order to fully define a linear gradient we need 2 (x,y) points on the plane - a start point and end point as shown in the picture below.
Note that these points should be in the coordinate system of the view, that is why are using mBounds variable. The shader mode is set to CLAMP so that outside these bounds the color of the corresponding point is used.
Then comes some math. We set the default "view angle" to the direction from left-bottom to top-right. After that, if there is a direction set, we calculate these 2 gradient points as an intersection of the rectangle's outer circle and the direction line passing through the center of the rectangle. If the direction vector is zero then both gradient colors are set to transparent and no border is drawn (view angle "from top"). First we calculate the radius of rectangle's outer circle - the distance from the center of the rectangle to its corners. Then we calculate a normalization factor and finally put the view direction vector in the center of the rectangle and multiply by normalization factor in order to put its endpoint on the outer circle. The gradient is ready.
In the picture below you can see the result of drawing a round rectangle border with a linear gradient shader:
The final step is to set the "view angle" based on gyroscope values:
Code:
public void onGyroChanged(float xAngle, float yAngle) {
mXAngle = xAngle;
mYAngle = yAngle;
invalidate();
}
This function sets the new angle values and calls invalidate() to redraw self.
The gyroscope processing is out of the scope of this post, so I will just paste the code here. It is mostly copied from Android documentation:
Code:
public class GyroHelper implements SensorEventListener {
private static final float NS2S = 1.0f / 1000000000.0f;
private Display mDisplay;
private boolean mStarted = false;
private SensorManager mManager;
private long mLastTime = 0;
private float mAngleX = 0.0f;
private float mAngleY = 0.0f;
public GyroHelper(Context c) {
mManager = (SensorManager) c.getSystemService(Context.SENSOR_SERVICE);
WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
mDisplay = wm.getDefaultDisplay();
}
public static boolean canBeStarted(Context c) {
SensorManager manager = (SensorManager) c.getSystemService(Context.SENSOR_SERVICE);
return manager.getDefaultSensor(Sensor.TYPE_GYROSCOPE) != null;
}
public void start() {
mStarted = false;
Sensor sensor = mManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
if (sensor == null) {
return;
}
mStarted = true;
reset();
mManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI);
}
public void stop() {
mStarted = false;
reset();
mManager.unregisterListener(this);
}
public boolean isStarted() {
return mStarted;
}
public float getXAngle() {
switch (mDisplay.getRotation()) {
case Surface.ROTATION_0: return -mAngleY;
case Surface.ROTATION_90: return -mAngleX;
case Surface.ROTATION_180: return mAngleY;
case Surface.ROTATION_270: return mAngleX;
}
return mAngleX;
}
public float getYAngle() {
switch (mDisplay.getRotation()) {
case Surface.ROTATION_0: return -mAngleX;
case Surface.ROTATION_90: return mAngleY;
case Surface.ROTATION_180: return mAngleX;
case Surface.ROTATION_270: return -mAngleY;
}
return mAngleY;
}
@Override
public void onSensorChanged(SensorEvent event) {
if (mLastTime != 0) {
final float dT = (event.timestamp - mLastTime) * NS2S;
mAngleX += event.values[0] * dT;
mAngleY += event.values[1] * dT;
}
mLastTime = event.timestamp;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private void reset() {
mLastTime = 0;
mAngleX = 0.0f;
mAngleY = 0.0f;
}
}
Somebody needs to start this GyroHelper and periodically call BorderItemView.onGyroChanged(GyroHelper.getXAngle(), GyroHelper.getYHelper()). That can be done right when onSensorChanged() is fired, but it is not a good idea since that can be too often, you might want to have your own timer controlling your frame rate, sensor updates can come 200 times in a second.
Finally, to see this code in action, you can have a look at the app itself, its free:
Google Play:
Direct link:
Download
It would be nice to get some comments and suggestions, let me know your thoughts!

Categories

Resources