Superpowered SDK Android - java

Hello i want to create a player with superpowered sdk but i can't exit from loop. When the song ends, he starts playing again, as it removed?
С++ void for start and pause playing;
void SuperpoweredExample::onPlayPause(bool play) {
pthread_mutex_lock(&mutex);
if (!play) {
playerA->pause();
playerB->pause();
} else {
bool masterIsA = (crossValue <= 0.5f);
playerA->play(!masterIsA);
playerB->play(masterIsA);
};
pthread_mutex_unlock(&mutex);
}
This void in JAVA
public void SuperpoweredExample_PlayPause(View button) { // Play/pause.
playing = !playing;
onPlayPause(playing);
Button b = (Button) findViewById(R.id.playPause);
b.setText(playing ? "Pause" : "Play");
}
And player initialize and play options in C++
SuperpoweredAdvancedAudioPlayer *playerA = *((SuperpoweredAdvancedAudioPlayer **)clientData);
playerA->setBpm(126.0f);
playerA->setFirstBeatMs(1);
playerA->setPosition(playerA->firstBeatMs, false, false);
playerA->exitLoop(); // not work
playerA->looping = false; // not work
playerA->togglePlayback();
playerA = new SuperpoweredAdvancedAudioPlayer(&playerA , playerEventCallbackA, samplerate, 0);
playerA->open(path, params[0], params[1]);

Handle playback state in your method playerEventCallbackA from
playerA = new SuperpoweredAdvancedAudioPlayer(&playerA , playerEventCallbackA, samplerate, 0);
It is the callback for main player events.
If you look at SuperpoweredAdvancedAudioPlayer.h class you will find
typedef enum SuperpoweredAdvancedAudioPlayerEvent {
SuperpoweredAdvancedAudioPlayerEvent_LoadSuccess,
SuperpoweredAdvancedAudioPlayerEvent_LoadError,
SuperpoweredAdvancedAudioPlayerEvent_EOF,
SuperpoweredAdvancedAudioPlayerEvent_JogParameter,
SuperpoweredAdvancedAudioPlayerEvent_DurationChanged,
} SuperpoweredAdvancedAudioPlayerEvent;
And when you receive SuperpoweredAdvancedAudioPlayerEvent_EOF event you can pause or do whatever you want with playback.
E.g.
static void playerEventCallbackA(void *clientData, SuperpoweredAdvancedAudioPlayerEvent event, void *value) {
SuperpoweredAdvancedAudioPlayer *playerA = *((SuperpoweredAdvancedAudioPlayer **)clientData);
if (event == SuperpoweredAdvancedAudioPlayerEvent_LoadSuccess) {
// handle player prepared
} else if (event == SuperpoweredAdvancedAudioPlayerEvent_LoadError) {
// handle error with player
} else if (event == SuperpoweredAdvancedAudioPlayerEvent_EOF && !loopingA) {
playerA->pause();
}
}
Hope it helps.

Related

Media Player loading media again and again

I am making a chat application and I have implemented the feature for sending audio messages.But here I find one thing which I don't want it to happen.It is that whenever my adapter gets updated,The media player starts loading again. In this way there will be an issue for if someone is listening to an audio and the user at other end sends a message ,the media player stops and it loads again.Here is the code of my adapter.
final MediaPlayer mediaPlayer;
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
handler = new Handler();
try {
mediaPlayer.setOnCompletionListener(mediaPlayer1 -> {
mediaPlayer1.stop();
binding.audioSeekbar.setProgress(0);
});
if (mediaPlayer.isPlaying()){
mediaPlayer.stop();
mediaPlayer.release();
}
mediaPlayer.setDataSource(finalUrlToLoad[1]);
mediaPlayer.setVolume(1f, 1f);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(mediaPlayer1 -> {
int totalDuration = mediaPlayer1.getDuration();
binding.totalDurationAudio.setText(createTimeLabel(totalDuration));
binding.loadingAudio.setVisibility(GONE);
binding.playPauseAudio.setVisibility(VISIBLE);
});
} catch (IOException e) {e.printStackTrace();}
binding.playPauseAudio.setOnClickListener(view -> {
if (mediaPlayer.isPlaying()){
handler.removeCallbacks(runnable);
mediaPlayer.pause();
binding.playPauseAudio.setImageResource(R.drawable.pause_to_play);
Drawable drawable = binding.playPauseAudio.getDrawable();
if( drawable instanceof AnimatedVectorDrawable) {
AnimatedVectorDrawable animation = (AnimatedVectorDrawable) drawable;
animation.start();
}
}else {
mediaPlayer.seekTo(binding.audioSeekbar.getProgress());
mediaPlayer.start();
handler.post(runnable);
binding.playPauseAudio.setImageResource(R.drawable.play_to_pause);
Drawable drawable = binding.playPauseAudio.getDrawable();
if( drawable instanceof AnimatedVectorDrawable) {
AnimatedVectorDrawable animation = (AnimatedVectorDrawable) drawable;
animation.start();
}
}
});
runnable = () -> {
int totalTime = mediaPlayer.getDuration();
binding.audioSeekbar.setMax(totalTime);
int currentPosition = mediaPlayer.getCurrentPosition();
binding.audioSeekbar.setProgress(currentPosition);
binding.totalDurationAudio.setText(createTimeLabel(totalTime));
Log.d("time", String.valueOf(currentPosition));
handler.postDelayed(runnable,1000);
};
binding.audioSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (b){
mediaPlayer.seekTo(i);
seekBar.setProgress(i);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
mediaPlayer.setOnBufferingUpdateListener((mediaPlayer1, i) -> binding.audioSeekbar.setSecondaryProgress(i));
Here finalurltoload[1] is the url for the audio.
Now what do I need to do in order to prevent loading it again and again.
I will be really grateful to who answer this question.
Thanks😊.
It's hard to tell from this code but I assume this is all set in your onBind event? If so, then this means every time RecyclerView creates a new holder and binds it, the associated media will be prepped and loaded, and whichever is the 'last holder to have been called with onBind, "wins" (and is what MediaPlayer will be loaded with). Since by default RecyclerView typically creates multiple holders up front, you are seeing your MediaPlayer being "loaded" multiple times.
You probably just don't want to do the initialization of each audio message in the onBind. Instead, just use the onBind event to initialize state variables (duration, progress, etc.) to some default value, hide them and bind the specific audio Uri. Then when the user takes some action like tapping on the holder, you unhide an indeterminate progress bar while the initialization takes place, and in the onPrepared() event unhide the state information (duration, progress, seekbar, etc.), and finally hide the indeterminate progress bar and start the audio.
I assume you are also sending over the sound file as part of your messaging app (i.e. not storing it on the web somewhere in a central location?), and this file gets stored in an app-specific storage location? If so, you don't need to worry about persisting the permission to that URI, but if that isn't the case you will.
First extract the media player code into singleton class like AudioManager.
Add few method like setMediaUpdateListener that set a callback for seek duration. and togglePlayPause to play or pause the audio.
Passed the message id or any unique identifier to the audio manager while playing the video.
In Adapter class onBind Method.
First Compare the id and playing Id is same like AudioManager.getInstance().isPlaying(messageId);
If yes then set the seekUpdatelistner to the audio manager class.
also update the play/pause icon based on AudioManager.isPlaying() method.
3.if user play other message by clicking play button. call AudioManager.play(message) method.In which we release the previous message and play the new one.
If current message is not playing then reset the view on non-playing state.
If Auto play is enabled then you need to check if audioManager is free then only you can play the last message otherwise ignored.
Like a class who are managing the audio for you and store all the state.
class AudioManager {
public static AudioManager instance;
final MediaPlayer mediaPlayer;
private AudioListener audioListener;
private Uri currentPlaying;
public AudioManager getInstance() {
if (instance == null) {
instance = new AudioManager();
}
}
public void play(Uri dataUri) {
if (mediaPlayer != null && currentPlaying == null || currentPlaying.equals(dataUri)) {
if (!mediaPlayer.isPlaying) {
mediaPlayer.play();
}
return;
} else if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
}
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
handler = new Handler();
try {
mediaPlayer.setOnCompletionListener(mediaPlayer1 -> {
mediaPlayer1.stop();
sendProgress(0);
});
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
}
mediaPlayer.setDataSource(dataUri;
mediaPlayer.setVolume(1f, 1f);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(mediaPlayer1 -> {
int totalDuration = mediaPlayer1.getDuration();
sendTotalDuration(totalDuration);
});
} catch (IOException e) {
e.printStackTrace();
}
}
public void pause() {
// update the pause code.
}
public void sendProgress(int progress) {
if (audioListener != null) {
audioListener.onProgress(progress);
}
}
public void sendTotalDuration(int duration) {
if (audioListener != null) {
audioListener.onTotalDuraration(duration);
}
}
public void AudioListener(AudioListener audioListener) {
this.audioListener = audioListener;
}
public interface AudioListener {
void onProgress(int progress);
void onTotalDuraration(int duration);
void onAudioPlayed();
void onAudioPaused():
}
}

MediaPlayer: Sounds playing over the top of each other

I have a soundboard with multiple buttons (approx 17), each linked to a .mp3 sound.
The issue is that when a sound is playing and I press another button, both are then playing in the background.
I would like to be able to stop the playing sound and start the new one when a different button is pressed. Also, is there the ability to stop the current playing sound by pressing on its button again?
Also, I don't really like the section of code that states: private MediaPlayer[] mPlayers = new MediaPlayer[17];
The number (in this case 17), determines the amount of times sounds can be played. After that, no further sounds can be played it seems. Is there a way of making this indefinite?
Rather than paste all of the code from my activity, I have attached the salient code and numbered it in the order in which it appears on my main activity .java file.
Thanks for your help all.
private int mNextPlayer = 0;
2) a.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.startAnimation(animAlpha);
startSound(R.raw.likethebattle);
}
});
3) public void onDestroy() {
super.onDestroy(); // <---------------------- This needed to be there
for (int i = 0; i < mPlayers.length; ++i)
if (mPlayers[i] != null)
try {
mPlayers[i].release();
mPlayers[i] = null;
} catch (Exception ex) {
// handle...
}
}
4) private void startSound(int id) {
try {
if (mPlayers[mNextPlayer] != null) {
mPlayers[mNextPlayer].reset();
mPlayers[mNextPlayer].prepare();
mPlayers[mNextPlayer].stop();
mPlayers[mNextPlayer].release();
mPlayers[mNextPlayer] = null;
}
mPlayers[mNextPlayer] = MediaPlayer.create(this, id);
mPlayers[mNextPlayer].start();
} catch (Exception ex) {
// handle
} finally {
++mNextPlayer;
mNextPlayer %= mPlayers.length;
}
}
It looks like you are not stoping currently playing MediaPlayer. startSound(id) does not stop currently playing sound. In
finally {
++mNextPlayer;
mNextPlayer %= mPlayers.length;
}
you move you counter to next player in array and next time you enter startSound() method your counter does not point to previously started player so it can not stop it.

Transport Controls not Updating after MediaPlayerService is destroyed

Okay. I have been struggling with this issue for a while.
Since the latest Wear OS upgrade, a play/pause transport control is displayed in the notification panel instead of showing media controls on a notification. My media player service works fine until it has been paused for some time and android destroys it as it has moved to the background. If the user selects the play button from the transport controls, the music starts playing as it should, but the transport controls no longer update meaning the user can only hit play and can no longer pause. This can be very frustrating if they need to stop audio and can't.
Here is the code where I initialize the media session. This is called at onCreate
private void initMediaSession() {
if (mediaSessionManager != null) return;
mediaSessionManager = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
//Create a new mediaSession
mediaSession = new MediaSessionCompat(getApplicationContext(), "com.turndapage.navmusic.mediaplayer");
//Get mediaSessions Transport Controls
mediaSession.getController().getTransportControls();
//Set Mediasession ready to receive media commands
mediaSession.setActive(true);
mediaSession.setFlags(
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
callback = new MediaSessionCompat.Callback() {
// Implement callbacks
#Override
public void onPlay() {
super.onPlay();
Cat.d("Playing from transport controls.");
// This is the event that is triggered from the transport controls
resumeMedia();
}
#Override
public void onPause() {
super.onPause();
Cat.d("Pausing from transport controls");
pauseMedia();
}
#Override
public void onSkipToNext() {
super.onSkipToNext();
skipToNext();
}
#Override
public void onSkipToPrevious() {
super.onSkipToPrevious();
skipToPrevious();
}
#Override
public void onStop() {
super.onStop();
stop();
}
#Override
public void onSeekTo(long position) {
super.onSeekTo(position);
mediaPlayer.seekTo((int)position);
}
#Override
public void onFastForward() {
super.onFastForward();
fastForward();
}
#Override
public void onRewind() {
super.onRewind();
rewind();
}
#Override
public void onPlayFromMediaId(String mediaId, Bundle extras) {
int id = Integer.parseInt(mediaId.replace("song", ""));
int thisIndex = 0;
for(Song song : songLibrary.getSongs()) {
if(song.getID() == id) {
ArrayList<Song> songs = getCurrentList();
thisIndex = songs.indexOf(song);
break;
}
}
int[] ids = new int[getCurrentList().size()];
for(int i = 0; i < ids.length; i++) {
ids[i] = getCurrentList().get(i).getID();
}
startPlaying(ids, thisIndex);
}
#Override
public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
KeyEvent event = mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
Cat.e("onMediaButtonEvent called: " + event);
if (event.getAction() == KeyEvent.ACTION_UP) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_MEDIA_PAUSE:
pauseMedia();
break;
case KeyEvent.KEYCODE_MEDIA_PLAY:
playMedia();
break;
case KeyEvent.KEYCODE_MEDIA_NEXT:
//skipToNext();
break;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
//skipToPrevious();
break;
}
}
return super.onMediaButtonEvent(mediaButtonEvent);
}
};
// Attach a callback to receive MediaSession update
mediaSession.setCallback(callback);
setSessionToken(mediaSession.getSessionToken());
}
This method is called when the user clicks the play transport control
public void resumeMedia() {
wasPlaying = true;
if(mediaPlayer != null) {
try {
if (!getPlaying()) {
mediaPlayer.seekTo(resumePosition);
mediaPlayer.start();
sendPlayPauseUpdate(true);
buildNotification(true);
}
ComplicationHelper.updatePlayPause(this, true);
} catch (IllegalStateException ex) {
ex.printStackTrace();
//restoreState();
startMediaPlayer();
}
}
}
the send play/pause update just sends a broadcast to the activity to update controls there.
Inside the notification code, I have this to update the playback state of the media session. As you can see, the pause or play actions are only added based on whether the media player is playing or not. Despite this, the play action is still displayed:
long actions = MEDIA_SESSION_ACTIONS;
if(isPlaying)
actions |= PlaybackStateCompat.ACTION_PAUSE;
else
actions |= PlaybackStateCompat.ACTION_PLAY;
mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
.setActions(actions)
.setState(isPlaying ? PlaybackStateCompat.STATE_PLAYING :
PlaybackStateCompat.STATE_PAUSED, resumePosition, 1)
.build());
and here are the media session actions:
// Media Session Actions
private static final long MEDIA_SESSION_ACTIONS =
PlaybackStateCompat.ACTION_SEEK_TO |
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
PlaybackStateCompat.ACTION_SKIP_TO_NEXT |
PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH |
PlaybackStateCompat.ACTION_PREPARE |
PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH |
PlaybackStateCompat.ACTION_PLAY_PAUSE |
PlaybackStateCompat.ACTION_STOP |
PlaybackStateCompat.ACTION_FAST_FORWARD |
PlaybackStateCompat.ACTION_REWIND;
What I have tried:
Changing media session to static and back
making the callback a variable rather than a making a new one when created.
Manually setting the mediasession's playback state to playing after play from transport controls
This works find on the phone app although I am using a pending intent to send a start command to run the resume function rather than transport controls. I am also able to resume playback from the watch's transport controls if I am using the phone to play audio and the controls update correctly even though the phone app is using the exact same class.
Please let me know if any other information could be helpful.
Thanks!
-Joel

How do I implement Google Play Game services in my app in Android Studio?

I'm trying to figure out exactly how to implement Google Play Game services in my app. On the Google Play Developer Console I've linked the game the relevant app using the SHA1 key and I know how to add leaderboards and achievements on here. I have also installed the Google Play services and Google Repository to Android Studio and added the dependency into build.gradle (as explained here: http://developer.android.com/google/play-services/setup.html) but I wasn't sure how to do the last 2 steps on that page (creating a Proguard exception and ensuring devices have the Google Play services APK) and if they are necessary - the latter of which even the Google Play Games sample projects don't seem to do.
Moreover, I'm not sure what code I actually need to put in my project to enable leaderboards and achievements, since according to this guide: https://developers.google.com/games/services/android/achievements, I use this code:
Games.Achievements.unlock(mGoogleApiClient, "my_achievement_id");
to unlock an achievement, for example, but there are no instructions on how I set up mGoogleApiClient. I've looked at the sample projects but it's still not clear what I'm supposed to do. Am I meant to copy and paste all of the code into my project? Are there certain sections I'm supposed to copy and paste? Do I have to write my own code for signing in to Google Play Games?
You should use getApiClient() instead of mGoogleApiClient.
Assuming you have an activity with a layout containing four buttons:
Leaderboard button - To launch the leaderboards,
Achievement button - To launch achievements
Sign in and Sign out buttons
For leaderboard, we push scores for best minutes, best distance covered and an overall highscore.
And for achievements, we unlock four achievements - survivor, warrior, lord, pride based on certain conditions.
Here's how you'd go about it:
public class GMSActivity extends BaseGameActivity implements OnClickListener{
Button lead;
Button achv;
final int RC_RESOLVE = 5000, RC_UNUSED = 5001;
//your game score. so we can push to cloud
int hS = 0;
//flags for achievements
boolean survivor;
boolean tribalWarriror;
boolean akonfemLord;
boolean zuluPride;
LinearLayout signInBar;
LinearLayout signOutBar;
Resources r;
private float bestTimeInSeconds;
private int bestTimeInMinutes;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.gms_layout);
r = getResources();
lead = (Button)findViewById(R.id.leaderboards);
achv = (Button)findViewById(R.id.achievements);
hS = loadScores();
findViewById(R.id.sign_in_button).setOnClickListener(this);
findViewById(R.id.sign_out_button).setOnClickListener(this);
lead.setOnClickListener(this);
achv.setOnClickListener(this);
signInBar = (LinearLayout)findViewById(R.id.sign_in_bar);
signOutBar = (LinearLayout)findViewById(R.id.sign_out_bar);
checkForAchievements();
if (isSignedIn()) {
onSignInSucceeded();
}else{
onSignInFailed();
}
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v == lead){
if (isSignedIn()) {
startActivityForResult(Games.Leaderboards.getAllLeaderboardsIntent(getApiClient()), RC_UNUSED);
} else {
showAlert(getString(R.string.leaderboards_not_available));
}
}else if(v ==achv){
if (isSignedIn()) {
startActivityForResult(Games.Achievements.getAchievementsIntent(getApiClient()), RC_UNUSED);
} else {
showAlert(getString(R.string.achievements_not_available));
}
}else if(v.getId() == R.id.sign_in_button){
beginUserInitiatedSignIn();
}else if(v.getId() == R.id.sign_out_button){
signOut();
hello.setText(getString(R.string.signed_out_greeting));
signInBar.setVisibility(View.VISIBLE);
signOutBar.setVisibility(View.GONE);
}
#Override
public void onSignInFailed() {
hello.setText(getString(R.string.signed_out_greeting));
signInBar.setVisibility(View.VISIBLE);
signOutBar.setVisibility(View.GONE);
}
#Override
public void onSignInSucceeded() {
signInBar.setVisibility(View.GONE);
signOutBar.setVisibility(View.VISIBLE);
// Set the greeting appropriately on main menu
Player p = Games.Players.getCurrentPlayer(getApiClient());
String displayName;
if (p == null) {
// Log.w(TAG, "mGamesClient.getCurrentPlayer() is NULL!");
displayName = "";
} else {
displayName = p.getDisplayName();
}
// hello.setText("Hello, " + displayName);
pushAccomplishments();
Toast.makeText(this, getString(R.string.your_progress_will_be_uploaded),
Toast.LENGTH_LONG).show();
}
//check for achievements and unlock the appropriate ones
void checkForAchievements() {
// Check if each condition is met; if so, unlock the corresponding
// achievement.
bestTimeInSeconds = loadGameBestTimeSec();
if(bestTimeInSeconds >= 900){ //15 minutes
survivor = true;
tribalWarriror = true;
}
}
void pushAccomplishments() {
if (survivor)
Games.Achievements.unlock(getApiClient(), getString(R.string.achievement_survivor));
if (tribalWarriror)
Games.Achievements.unlock(getApiClient(), getString(R.string.achievement_tribal_warrior));
if(bestTimeInSeconds >= 60){ //1 minute atleast
bestTimeInMinutes = (int)bestTimeInSeconds/60;
Games.Leaderboards.submitScore(getApiClient(), getString(R.string.leaderboard_best_time_minutes), bestTimeInMinutes);
}
if(bestTimeInSeconds >= 10){ // 1 meter atleast
int bestDistance = (int)bestTimeInSeconds/10;
Games.Leaderboards.submitScore(getApiClient(), getString(R.string.leaderboard_best_distance_meters), bestDistance);
}
Games.Leaderboards.submitScore(getApiClient(), getString(R.string.leaderboard_top_score_points), hS);
}
#Override
//loading scores and achievements
private int loadScores() {
// TODO Auto-generated method stub
int score = 0;
try{
preferences = new SecurePreferences(getApplicationContext(),
"besiPreferences", "1234", true);
score = Integer.parseInt(preferences.getString("highScore"));
}catch(Exception e){}
return score;
}
private float loadGameBestTimeSec() {
float time = 0;
try{
preferences = new SecurePreferences(getApplicationContext(),
"besiPreferences", "1234", true);
time = Float.parseFloat(preferences.getString("gameTimeSec"));
}catch(Exception e){}
return time;
}
private int loadCalabashesCompleted() {
try{
preferences = new SecurePreferences(getApplicationContext(),
"makolaPref", "1234", true);
return Integer.parseInt(preferences.getString("bookCompleted")== null ? "0" : preferences.getString("bookCompleted"));
}catch(Exception e){
return 0;
}
}
private int loadLevelCompleted() {
try{
preferences = new SecurePreferences(getApplicationContext(),
"makolaPref", "1234", true);
return Integer.parseInt(preferences.getString("levelCompleted")== null ? "0" : preferences.getString("levelCompleted"));
}catch(Exception e){
return 0;
}
}
}

Implementing strobe (Flash Light Blinking) effect on android which blinks with the same frequency

I am implementing strobe functionality which works fine ( the LED camera flash light turn on/off) the problem that i occurring is that the turn on/off with different frequency in different devices. In HTC SensationXE its blinking fast and in NEXUS its blinking slow dont know what the issue is. Can anyone help please:
Here is code:
/*
* This method turn on the LED camera flash light
*/
public void flashLightOn() {
Log.d("Time", "On");
if (!isFlashOn) {
if (cam != null || params != null) {
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(params);
cam.startPreview();
isFlashOn = true;
} else {
cam = Camera.open();
params = cam.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(params);
cam.startPreview();
isFlashOn = true;
}
}
else{
return;
}
}
/*
* This method turn off the LED camera flash light
*/
public void flashLightOff() {
Log.d("Time", "Off");
if (isFlashOn) {
if (cam != null || params != null) {
//params.setFlashMode(Parameters.FLASH_MODE_OFF);
//cam.setParameters(params);
cam.stopPreview();
isFlashOn = false;
}
else{
//params = cam.getParameters();
//params.setFlashMode(Parameters.FLASH_MODE_OFF);
//cam.setParameters(params);
cam.stopPreview();
isFlashOn = false;
}
}
else{
return;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
mHolder = holder;
try {
cam.setPreviewDisplay(mHolder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
cam.stopPreview();
mHolder = null;
}
private final Runnable mRunnable = new Runnable() {
public void run() {
if (mActive) {
if (mSwap) {
flashLightOn();
mSwap = false;
mHander.postDelayed(mRunnable, strobeOnDelay);
} else {
flashLightOff();
mSwap = true;
mHander.postDelayed(mRunnable, strobeOffDelay);
}
}
}
};
My class is implemention SurfaceHolder.Callback
The run method calls the delay operations with fixed parameters. That means the delay will take the processing time of everything else on the computer plus the delay period. The "everything else" may appear to be small and quick within your code but it will also include work by all the other processes that compete for processor time etc.
Your code simplifies to:
LoopForever
Do some processing to toggle light ON or OFF;
Delay for a fixed time;
EndLoop
A common way of handling regular activities is something like:
LoopForever
Do some processing to toggle light ON or OFF;
Calculate time interval until next toggle wanted.
Delay for the calculated interval;
EndLoop
Note that the calculation of the time interval would refer to the time-of-day clock and compare time-now against time-wanted. That way any variations between how fast one loop executes compared to another would be ignored. The code always works out what time the next toggle is wanted and waits until then. Hence over a long period the rate should be correct, although the individual ON and OFF times may be slightly inaccurate.

Categories