Better way to make LED light on back-facing camera blink? - android

I am trying to make the LED light on my back-facing camera blink every N seconds:
private void blink() {
for (int i = 0; i < 5; i++) {
turnOnLedLight();
try {
Thread.sleep(1000); // N = 1 second
}
catch (InterruptedException e) {
Log.e("Test", "Got interrupted.");
}
turnOffLedLight();
}
}
private static Camera camera = null;
private void turnOnLedLight() {
camera = Camera.open();
Parameters p = camera.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
}
private void turnOffLedLight() {
camera.stopPreview();
camera.release();
camera = null;
}
The code above works, but is there a better approach besides putting the thread to sleep? The blink method is called in the doInBackground method in an AsyncTask.
Update
I realized that the code above makes the LED light stay on for N seconds. I want to know whether there is a better way to make it stay on for N seconds and stay off for N seconds.

I'd do it in an alarm via alarmManager. You're holding up the AsyncTask thread. As of 3.0, Async tasks all share a thread and are executed round robin. This means in you have any other async tasks, it would be blocked. In addition an Alarm will wake the phone if it goes to sleep, if the phone goes to sleep while you're in your thread the thread will be paused and will be frozen in its current state of blinking until the user wakes it.
I'd also do Camera.open only once, when you first want the camera, and release it when you no longer want it anymore, rather than request it in each turnOnLedLight (causing you to get and release the camera 5 times). Right now if someone changed apps while you were off and opened the camera app, you could be locked out from getting the camera again (and likely crash).

you can use System.currentTimeMillis() if you're trying to make it more accurate,like:
long previousTimeMillis = System.currentTimeMillis();
int i = 0;
while(i < 5){
if(System.currentTimeMillis() - previousTimeMillis >= 1000){
turnOffLedLight();
previousTimeMillis = System.currentTimeMillis();
i++;
}else{
turnOnLedLight();
}
}
and here's what you can do to make led stay on and off for N seconds:
long previousTimeMillis = Sustem.currentTimeMillis();
boolean shouldTurnOnLight = true;
int i = 0;
while(i < 5){
if(System.currentTimeMillis() - previousTimeMillis >= 1000){
if(shouldTurnOnLight){
turnOnLedLight();
shouldTurnOnLight = false;
}else{
turnOffLedLight();
shouldTurnOnLight = true;
}
previousTimeMillis = System.currentTimeMillis();
i++;
}
}

Here's another way to do it if your on/off cycle is symmetrical:
public Boolean ledOn = false;
...
// Change the LED state once a second for 5 minutes:
CountDownTimer cdt = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
ledOn = !ledOn;
if (ledOn)
turnOffLedLight();
else
turnOnLedLight();
}
public void onFinish() {
Log.d(TAG, "LED is on? "+ ledOn.toString());
}
};
...
cdt.start();
...
cdt.cancel();
(Edited to better handle starting/stopping.)

Related

Android Studio Mediaplayer how to fade in and out

I am working with the mediaplayer class in android studio. I simply want to fade out one sound and fade in the other sound instead of using setVolume(0,0) and setVolume(1,1).
I have created two mediaplayers for this and it seemed like I found a solution in this thread: Android: How to create fade-in/fade-out sound effects for any music file that my app plays? but I don't know how to use deltaTime.
There are also some other solutions to this, which I can barely understand. Isn't there an easy way to cross fade two mediaplayers, I can not imagine no one has needed this yet or everyone uses obsessive code to achieve it. And how should I use deltaTime?
Looking at the linked example, you would have to call fadeIn()/fadeOut() in a loop, to increase/decrease the volume over a period of time. deltaTime would be the time between each iteration of the loop.
You'd have to do this in a separate thread from your main UI thread, so you don't block it and cause your app to crash. You can do this by either putting this loop inside a new Thread/Runnable/Timer.
Here is my example for fading in (you can do a similar thing for fading out):
float volume = 0;
private void startFadeIn(){
final int FADE_DURATION = 3000; //The duration of the fade
//The amount of time between volume changes. The smaller this is, the smoother the fade
final int FADE_INTERVAL = 250;
final int MAX_VOLUME = 1; //The volume will increase from 0 to 1
int numberOfSteps = FADE_DURATION/FADE_INTERVAL; //Calculate the number of fade steps
//Calculate by how much the volume changes each step
final float deltaVolume = MAX_VOLUME / (float)numberOfSteps;
//Create a new Timer and Timer task to run the fading outside the main UI thread
final Timer timer = new Timer(true);
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
fadeInStep(deltaVolume); //Do a fade step
//Cancel and Purge the Timer if the desired volume has been reached
if(volume>=1f){
timer.cancel();
timer.purge();
}
}
};
timer.schedule(timerTask,FADE_INTERVAL,FADE_INTERVAL);
}
private void fadeInStep(float deltaVolume){
mediaPlayer.setVolume(volume, volume);
volume += deltaVolume;
}
Instead of using two separate MediaPlayer objects, I would in your case use just one and swap the track between the fades.
Example:
**Audio track #1 is playing but coming to the end**
startFadeOut();
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.setDataSource(context,audiofileUri);
mediaPlayer.prepare();
mediaPlayer.start();
startFadeIn();
**Audio track #2 has faded in and is now playing**
Hope this solves your problem.
Here's the fade-out code in case it saves someone some time.
This also includes a stopPlayer() function to release the MediaPlayer from memory. It's a good practice to do so.
// Set to the volume of the MediaPlayer
float volume = 1;
private void startFadeOut(){
// The duration of the fade
final int FADE_DURATION = 3000;
// The amount of time between volume changes. The smaller this is, the smoother the fade
final int FADE_INTERVAL = 250;
// Calculate the number of fade steps
int numberOfSteps = FADE_DURATION / FADE_INTERVAL;
// Calculate by how much the volume changes each step
final float deltaVolume = volume / numberOfSteps;
// Create a new Timer and Timer task to run the fading outside the main UI thread
final Timer timer = new Timer(true);
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
//Do a fade step
fadeOutStep(deltaVolume);
//Cancel and Purge the Timer if the desired volume has been reached
if(volume <= 0){
timer.cancel();
timer.purge();
stopPlayer();
}
}
};
timer.schedule(timerTask,FADE_INTERVAL,FADE_INTERVAL);
}
private void fadeOutStep(float deltaVolume){
player.setVolume(volume, volume);
volume -= deltaVolume;
}
// Release the player from memory
private void stopPlayer() {
if (player != null) {
player.release();
player = null;
}
}
There's a VolumeShaper class added in API Level 26 (https://developer.android.com/guide/topics/media/volumeshaper).
Here's an example of volume out and in, you can shape the fade in or out speed (ramp) adding more points to times and volumes arrays.
Time points must start at 0 and end at 1 and they are relative times of volume ramping.
fun fadeOutConfig(duration: Long): VolumeShaper.Configuration {
val times = floatArrayOf(0f, 1f) // can add more points, volume points must correspond to time points
val volumes = floatArrayOf(1f, 0f)
return VolumeShaper.Configuration.Builder()
.setDuration(duration)
.setCurve(times, volumes)
.setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_CUBIC)
.build()
}
fun fadeInConfig(duration: Long): VolumeShaper.Configuration {
val times = floatArrayOf(0f, 1f) // can add more points, volume points must correspond to time points
val volumes = floatArrayOf(0f, 1f)
return VolumeShaper.Configuration.Builder()
.setDuration(duration)
.setCurve(times, volumes)
.setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_CUBIC)
.build()
}
fun fadeInOrOutAudio(mediaPlayer: MediaPlayer, duration: Long, out: Boolean) {
val config = if (out) fadeOutConfig(duration) else fadeInConfig(duration)
val volumeShaper = mediaPlayer.createVolumeShaper(config)
volumeShaper.apply(VolumeShaper.Operation.PLAY)
}
private void fadeOut() {
final long steps = 30;
final double stepWidth = (double) 1 / steps;
mFadeOutCriteria = 1;
handler.postDelayed(new Runnable() {
#Override
public void run() {
mFadeOutCriteria -= stepWidth;
mediaPlayer.setVolume(mFadeOutCriteria, mFadeOutCriteria);
if (mFadeOutCriteria <= 0) {
mediaPlayer.stop();
nextrunq();
mFadeOutCriteria = 0;
handler.removeCallbacks(this);
} else
handler.postDelayed(this, 100);
}
}, 100);
}

Doing an Android FPS counter

I'm trying to do an FPS counter for any Android app. That means I don't have the source code for that app (I can't modify it or anything like that, I just have the .apk).
I've researched a lot into this and I've found only one app that does this (it's called Game Bench, you can find it on Google Play), so it is possible somehow. When the app starts, it has a list with all the games on your phone, you choose one and Game Bench automatically starts it and calculates the FPS. I need a similar behaviour.
Now, what I am asking is, if any of you has at least an idea of how I could calculate the FPS of an app (without writing code in it). Doing research I found a few vague ones, like record the screen and calculate FPS of the video, or somehow calculate the FPS using data collected with systrace. But on both these "ideas" there is very few info on the internet.
So please, if you guys have any information about this matter/ ideas/ opinions, I'll be happy to hear them. Thanks!
This is an example of how I would bench FPS using a Surface View.
Look at the Run method to see how the FPS works.
1: We get the time before update and render to the screen.
2: After all work is done we get the time again.
3: 1000 milliseconds is a second and 40 FPS is the norm.
4: elaspedTime = startTime - endTime;
5: So if elaspedTime is under 25 then its at-least doing 40 FPS.
6: If elaspedTime = 5 milliseconds then its doing 1000 / 5 = 200 FPS
7: You can sleep the thread for a couple milliseconds if you are running the updater and renderer on the same thread. That way you're not updating to many times.
8: Hope it helps this class is a basic game class that keeps the game running and 40 fps even if they are running it on a Galaxy S 6. You would want to make your own necessary changes to tweak it more.
public class MySurfaceView extends SurfaceView implements Runnable {
long time = 0, nextGameTick = 0;
SurfaceHolder myHolder;
Thread myThread = null;
boolean myRunning = false;
public MySurfaceView(Context context) {
super(context);
myHolder = getHolder();
}
#Override
public void run() {
while (myRunning) {
nextGameTick = System.currentTimeMillis();
if (!myHolder.getSurface().isValid())
continue;
Update();
Render();
time = nextGameTick - System.currentTimeMillis();
time = (time <= 0) ? 1 : time;
if (time <= 25)
sleepThread(25 - time);
Log.d("FrameRate", String.valueOf(1000 / time));
}
}
public void pause() {
myRunning = false;
while (true) {
try {
myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
myThread = null;
}
public void resume() {
myRunning = true;
myThread = new Thread(this);
myThread.start();
}
public void sleepThread(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void Render() {
// TODO Render to Screen
}
private void Update() {
// TODO Update
}
}

Regarding Game Time in Libgdx

I have actor Rectangle and powerUp Rectangle and I want that when It collides with actor will have power for 10 seconds. This was achieved as follows :
if (powerBoxRect.overlaps(actorRectObj)) {
powerUpTime = System.currentTimeMillis() + 10000;
}
if (powerUpTime > System.currentTimeMillis()) {
powerActor = IMMUNEACTOR;
}
But as I have taken any power and press pause button my game is go to paused state and after 10 seconds when I resume my game,power is lost because meanwhile system time is running.
I want to know that how can I stop system time or libgdx provides any other feature to handle this situation?
float time = 0;
int maxTime = 3;
public void update() {
time += Gdx.graphics.getDeltaTime();
if(time > maxTime) {
// DO YOUR THING
}
}

Time delays and game loop

I'm doing a simple match-3 game and I'm currently using a game loop like the code below. I'm using some frame calculations for optimal speed of th game. I took this from another game that I have done before. But this seems unnecessary for this type of game.
I need to have some time delays at several places, like when I have moved an object on the game area, I want a short time delay before the call to an method that check if there is a match of three objects in a row. And then I also need a short time delay when the code has detect a match, so that I can do some simple effect at those positions in the game grid before the user starts to move another object and then check for a match.
As it is now every thing happens at once and I wonder if it would be better to run this game without this calculations of frames and how I could do instead to get some time delays?
I have tested to use Thread.sleep(250) inside this code, but didn't worked the way I hade hoped for.
What could be a better approach for running a game like this?
// Game loop ---------------------------------------
#Override
public void run() {
// TODO Auto-generated method stub
long beginTime;
long timeDiff;
int sleepTime;
int framesSkipped;
sleepTime = 0;
while (gameRunning) {
if (!surfaceHolder.getSurface().isValid())
continue;
try {
canvas = surfaceHolder.lockCanvas();
beginTime = System.currentTimeMillis();
framesSkipped = 0;
// Different game states
switch (gameState) {
case 0: // Intro game
drawStartPage(canvas);
break;
case 1: // Play game
canvas.drawRGB(0,0,0);
if(touchActionDown) {
touchActionDown = false;
colorObjectManager.checkPosition(touchX, touchY);
touchActionMove = false;
}
if(touchActionMove) {
touchActionMove = false;
colorObjectManager.swapObject(moveDirection);
// Time delay
colorObjectManager.checkMatch();
// Time delay
}
// Call method to draw objects on screen
colorObjectManager.drawObjectsList(canvas);
break;
case 2: // End game
break;
}
// Calculate difference from first call to
// System.currentTimeMillis() and now
timeDiff = System.currentTimeMillis() - beginTime;
// Calculate sleepTime
sleepTime = (int) (FRAME_PERIOD - timeDiff);
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
// Call method to only update objects on screen
updateObjects();
sleepTime += FRAME_PERIOD;
framesSkipped++;
}
} finally {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // End while-loop
}
// End game loop ---------------------------------------
I suggest use libgdx its a simple frameWork and you dont need to Calculate the DeltaTime.
AFAIK Dont use the Thread sleep on a surfaceholder use a seperate thread and lock the canvas.
you can use android animations. fadein fadeout to be fancy.
//some other method to delay
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
// your code here
}
}, 1000/* 1sec delay */);
also got a very lame solution
//for 5 second of delay
for(int i=0;i<5000:i++){
for(int k=0;k<5000:k++){
for(int j=0;j<5000:j++){
}
}
}

Android Development: Game background loop

I'm developing a 2d Game using Canvas/Surfaceview and have a problem with thread.
So what I want to accomplish is something in the background that is for example:
for each second SpawnEnemy() or ticking seconds or attacking.
I tried Thread.wait but that just cause pain and make my game 2fps.
here is my gameLoop:
import android.graphics.Canvas;
public class GameLoopThread extends Thread {
static final long FPS = 20;
private GameView view;
private boolean running = false;
public GameLoopThread(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
#Override
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS - (System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {}
}
}
}
So I want something that is ticking in the background (seconds) that doesn't thread.wait.
You should make your thread run the game normally about 60fps, see this example: How can I use the animation framework inside the canvas?
If you want for each second to do something then you either count frames in onDraw(), on each 60th frame do it, or if you need a greater precision then in each onDraw() check the system time and do something when a second has elapsed.
You should also consider using two methods one for drawing onDraw() and another for the game logic which are called from your thread.
you could use AsyncTask for something to run in background

Categories

Resources