I would like to control my squash score counter app via only one head set button. It means that I want to detect single or double click and add score to first or second player according to number of clicks.
I cannot use long click, instead of double click, because long click activate Google Now.
This is what I used in my music player to handle headset control single and double click.
static final long CLICK_DELAY = 500;
static long lastClick = 0; // oldValue
static long currentClick = System.currentTimeMillis();
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_MEDIA_BUTTON)) {
KeyEvent keyEvent = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
if (keyEvent.getAction() != KeyEvent.ACTION_DOWN)return;
lastClick = currentClick ;
currentClick = System.currentTimeMillis();
if(currentClick - lastClick < CLICK_DELAY ){
//This is double click
} else {
//This is single click
}
}
Too late, but maybe someone else will find it useful, with triple clicks like Google Music, Spotify, etc.
const val DOUBLE_CLICK_TIMEOUT = 430L
private var mHeadsetHookClickCounter = 0
override fun onMediaButtonEvent(mediaButtonEvent: Intent?): Boolean {
if (Intent.ACTION_MEDIA_BUTTON == mediaButtonEvent?.action) {
val ke = mediaButtonEvent.getParcelableExtra<KeyEvent>(Intent.EXTRA_KEY_EVENT)
if (ke != null && ke.keyCode == KeyEvent.KEYCODE_HEADSETHOOK) {
if (ke.action == KeyEvent.ACTION_UP) {
mHeadsetHookClickCounter = min(mHeadsetHookClickCounter+1, 3)
if (mHeadsetHookClickCounter == 3) {
handlingHeadsetClick()
} else {
Handler().postDelayed({
handlingHeadsetClick()
}, DOUBLE_CLICK_TIMEOUT)
}
}
return true
}
}
return super.onMediaButtonEvent(mediaButtonEvent)
}
private fun handlingHeadsetClick() {
logd("MediaSessionSupportFeature Handling headset click")
when(mHeadsetHookClickCounter) {
1 -> { service.get()?.togglePlayPause() }
2 -> { service.get()?.playNext() }
3 -> { service.get()?.playPrevious() }
}
// Reset Counter
mHeadsetHookClickCounter = 0
return
}
Related
I am creating a class witch loads up a few sounds. However, isPlaying keeps on throwing an exception after a while and then stops playing that particular sound permanently, while other sounds keep playing OK.
public class MySound {
int m_IdMyId;
int m_ResId;
boolean m_IsLoaded;
MediaPlayer m_Media;
public MySound(int idMyId, int resId){
m_IdMyId = idMyId;
m_ResId = resId;
m_IsLoaded = false;
m_Media = null;
}
}
In this m_IdMyId is just an id for my game. m_ResId is something like R.raw.mysound1. m_IsLoaded I think is automatically set to true as I am loading synconously. m_Media is the MediaPlayer object.
I am calling stop() very regularly, as it is a game and I need to check every second or so to make sure certain sounds are stopped. It is here that it throws an exception when snd.m_Media.isPlaying() is called.
I cannot seem to access e to see what the error is.
Also I would like to know how I can set m_IsLoaded correctly. How do I know when the sound is fully loaded and ready to use?
Here is my management class:
public class MySoundManager {
MainActivity m_Context;
ArrayList<MySound> mySounds;
public MySoundManager(MainActivity context) {
m_Context = context;
mySounds = new ArrayList<MySound>();
mySounds.add(new MySound(8, R.raw.mysound1));
mySounds.add(new MySound(10, R.raw.mysound2));
mySounds.add(new MySound(22, R.raw.mysound3));
mySounds.add(new MySound(100, R.raw.click));
mySounds.add(new MySound(101, R.raw.error));
for(MySound mysound : mySounds) {
mysound.m_Media = MediaPlayer.create(m_Context, mysound.m_ResId); // no need to call prepare(); create() does that for you
mysound.m_IsLoaded = true;
}
}
// I call this when the main thread calls onResume
public void onResume(){
for(MySound mysound : mySounds) {
if(mysound.m_Media == null) {
mysound.m_Media = MediaPlayer.create(m_Context, mysound.m_ResId); // no need to call prepare(); create() does that for you
mysound.m_IsLoaded = true;
}
}
}
// I call this when the main thread calls onPause
public void onPause(){
for(MySound mysound : mySounds) {
if(mysound.m_Media != null) {
mysound.m_Media.stop();
mysound.m_Media.release();
mysound.m_Media = null;
}
}
}
public boolean IsAllLoaded(){
for(MySound mysound : mySounds) {
if(!mysound.m_IsLoaded) return false;
}
return true;
}
public MySound FindMySoundByIdMyId(int idMyId){
try {
for(MySound mysound : mySounds) {
if (mysound.m_IdMyId == idMyId) return mysound;
}
}catch(Exception e) {
MySound snd;
snd = null; // ToDo
}
return null;
}
public void play(int idMyId){
MySound snd;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null)
snd.m_Media.start();
}catch(IllegalStateException e) {
snd = null; // ToDo
}
}
public void pause(int idMyId){
MySound snd;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null &&
snd.m_Media.isPlaying())
snd.m_Media.pause();
}catch(IllegalStateException e) {
snd = null; // ToDo
}
}
public void pauseAll(){
try{
for (MySound mysound : mySounds) {
if(mysound.m_Media.isPlaying())
mysound.m_Media.pause();
}
}catch(IllegalStateException e) {
MySound snd;
snd = null; // ToDo
}
}
public boolean isPlaying(int idMyId, MySound[] fill){
MySound snd;
fill[0] = null;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null){
fill[0] = snd;
return snd.m_Media.isPlaying();
}
}catch(IllegalStateException e) {
snd = null; // ToDo
}
return false;
}
public void stop(int idMyId){
MySound snd;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null &&
snd.m_Media.isPlaying())
snd.m_Media.stop();
}catch(IllegalStateException e) {
snd = null; // ToDo
}
}
// The str is in the format
// number id, 1 = on 0 = off,dont play if this id playing;
public void PlaySound(String str) {
boolean isplaying;
int i, len, id, idDontPlay, milliNow;
String[] strARR = str.split(";");
String[] strARR2;
Integer[] tmpIntARR;
ArrayList<Integer[]> onARR = new ArrayList<Integer[]>();
ArrayList<Integer> offARR = new ArrayList<Integer>();
MySound snd;
for (i = 0, len = strARR.length; i < len; i++) {
if(strARR[i].length() <= 0) continue;
if((strARR2 = strARR[i].split(",")) != null &&
strARR2.length >= 3 &&
strARR2[0].length() > 0 &&
strARR2[1].length() > 0 &&
strARR2[2].length() > 0){
id = Integer.parseInt(strARR2[0]);
idDontPlay = Integer.parseInt(strARR2[2]);
tmpIntARR = new Integer[2];
tmpIntARR[0] = id;
tmpIntARR[1] = idDontPlay;
if(Integer.parseInt(strARR2[1]) == 1){
onARR.add(tmpIntARR);
} else offARR.add(id);
}
}
// Turn off all sounds that need to be turned off
for (i=0,len=offARR.size();i<len;i++) {
id = offARR.get(i);
stop(id);
}
// Turn all sounds that need to be turned on,
// but only if the sound that blocks a new sound is not playing
for (i=0,len=onARR.size();i<len;i++) {
tmpIntARR = onARR.get(i);
id = tmpIntARR[0];
idDontPlay = tmpIntARR[1];
// We dont play if the idDontPlay sound is already playing
if((snd = FindMySoundByIdMyId(idDontPlay)) != null &&
snd.m_Media.isPlaying())
continue;
if((snd = FindMySoundByIdMyId(id)) != null){
isplaying = snd.m_Media.isPlaying();
milliNow = snd.m_Media.getCurrentPosition();
if(milliNow > (snd.m_Media.getDuration() - 1000) ||
(!isplaying && milliNow > 0)){
snd.m_Media.seekTo(0); // Half a second inside
}
if(!isplaying) snd.m_Media.start();
}
}
}
}
Creating a MediaPlayer instance for every sound is not a good practice to get low latency, especially for short clips. MediaPlayer is for longer clips such as Music files it uses large buffer so, larger buffer means high latency. Also, there is AudioFocus mechanism on Android that may interfere your sound playing session. So, I strongly recommend you to use SoundPool to play short clips like game sounds.
I'm trying to implement a fast-forward and rewind actions using PlaybackControlsRow using Leanback library for Android TV, however I can't find any method to detect a long press on these buttons. My current implementation is simple, only does seeking for 10 seconds on one click:
private void setupRows() {
final ClassPresenterSelector ps = new ClassPresenterSelector();
final PlaybackControlsRowPresenter playbackControlsRowPresenter =
new PlaybackControlsRowPresenter(new DescriptionPresenter());
playbackControlsRowPresenter.setOnActionClickedListener(action -> {
if (action.getId() == playPauseAction.getId()) {
togglePlayback(playPauseAction.getIndex() == PlayPauseAction.PLAY);
} else if (action.getId() == fastForwardAction.getId()) {
fastForward();
return;
} else if (action.getId() == rewindAction.getId()) {
rewind();
return;
}
if (action instanceof PlaybackControlsRow.MultiAction) {
((PlaybackControlsRow.MultiAction) action).nextIndex();
notifyChanged(action);
}
});
ps.addClassPresenter(PlaybackControlsRow.class, playbackControlsRowPresenter);
ps.addClassPresenter(ListRow.class, new ListRowPresenter());
rowsAdapter = new ArrayObjectAdapter(ps);
updatePlaybackControlsRow();
setAdapter(rowsAdapter);
}
private void fastForward() {
((PlaybackActivity) getActivity()).onFragmentFastForward();
final int currentTime = ((PlaybackActivity) getActivity()).getPosition();
playbackControlsRow.setCurrentTime(currentTime);
}
private void rewind() {
((PlaybackActivity) getActivity()).onFragmentRewind();
final int currentTime = ((PlaybackActivity) getActivity()).getPosition();
playbackControlsRow.setCurrentTime(currentTime);
}
In PlaybackActivity:
public void onFragmentFastForward() {
// Fast forward 10 seconds.
videoView.seekTo(videoView.getCurrentPosition() + (10 * 1000));
}
public void onFragmentRewind() {
videoView.seekTo(videoView.getCurrentPosition() - (10 * 1000));
}
Is it possible to implement fast-forward and rewind on long press of actions, like key-up/key-down events on the action buttons?
After looking for other solutions, seems that PlaybackControlsRowPresenter is designed in the way that it should have no long presses, but instead increasing/reducing speed by the number of clicks on fast-forward/rewind buttons. It can be clearly seen from internal constructor implementation of PlaybackControlsRowPresenter.FastForwardAction and PlaybackControlsRowPresenter.RewindAction classes:
/**
* Constructor
* #param context Context used for loading resources.
* #param numSpeeds Number of supported fast forward speeds.
*/
public FastForwardAction(Context context, int numSpeeds) {
So, as the result, my solution for now is increasing/reducing a speed by each click on the fast-forward/rewind buttons (which is done on UI by default). After that, when I click on play - it just resumes video from the seeked point.
UPDATE (updated parts of code):
private void setupRows() {
final ClassPresenterSelector ps = new ClassPresenterSelector();
final PlaybackControlsRowPresenter playbackControlsRowPresenter =
new PlaybackControlsRowPresenter(new DescriptionPresenter());
playbackControlsRowPresenter.setOnActionClickedListener(action -> {
if (action.getId() == playPauseAction.getId()) {
togglePlayback(playPauseAction.getIndex() == PlayPauseAction.PLAY);
((PlaybackControlsRow.MultiAction) action).nextIndex();
notifyChanged(action);
} else if (action.getId() == fastForwardAction.getId()) {
if (currentSpeed <= MAX_SPEED) {
currentSpeed++;
showTogglePlayback(false, true);
if (currentSpeed < 0) {
prevRewind();
} else if (currentSpeed > 0) {
nextFastForward();
} else {
currentSpeed++;
prevRewind();
nextFastForward();
}
((PlaybackActivity) getActivity()).seek(currentSpeed);
}
} else if (action.getId() == rewindAction.getId()) {
if (currentSpeed >= MIN_SPEED) {
currentSpeed--;
showTogglePlayback(false, true);
if (currentSpeed > 0) {
prevFastForward();
} else if (currentSpeed < 0) {
nextRewind();
} else {
currentSpeed--;
prevFastForward();
nextRewind();
}
((PlaybackActivity) getActivity()).seek(currentSpeed);
}
} else if (action.getId() == R.id.lb_control_picture_in_picture &&
PlaybackActivity.supportsPictureInPicture(getActivity())) {
getActivity().enterPictureInPictureMode();
}
});
ps.addClassPresenter(PlaybackControlsRow.class, playbackControlsRowPresenter);
ps.addClassPresenter(ListRow.class, new ListRowPresenter());
rowsAdapter = new ArrayObjectAdapter(ps);
updatePlaybackControlsRow();
setAdapter(rowsAdapter);
}
private void prevFastForward() {
fastForwardAction.setIndex(fastForwardAction.getIndex() - 1);
notifyChanged(fastForwardAction);
}
private void nextFastForward() {
fastForwardAction.nextIndex();
notifyChanged(fastForwardAction);
}
private void prevRewind() {
rewindAction.setIndex(rewindAction.getIndex() - 1);
notifyChanged(rewindAction);
}
private void nextRewind() {
rewindAction.nextIndex();
notifyChanged(rewindAction);
}
After opening application details settings using
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS), how can I force stop application programmatically?
You can use Accessibility to achieve that (but it needs Accessibility for your app turned on by user)
public class MyAccessibilityService extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
//TYPE_WINDOW_STATE_CHANGED == 32
if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event
.getEventType()) {
AccessibilityNodeInfo nodeInfo = event.getSource();
if (nodeInfo == null) {
return;
}
List<AccessibilityNodeInfo> list = nodeInfo
.findAccessibilityNodeInfosByViewId("com.android.settings:id/left_button");
//We can find button using button name or button id
for (AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
list = nodeInfo
.findAccessibilityNodeInfosByViewId("android:id/button1");
for (AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
#Override
public void onInterrupt() {
// TODO Auto-generated method stub
}
}
You can check it out in this example:
AccessibilityTestService.java
You have two ways, a more rude one and a better one
The good practice
If you have only one activity running
the this.finish(); method will be enough
If you have multiple activities running
You gotta call the this.finishAffinity(); method. This is the best practice in general cases, where you can have both a single or multiple activities
The rude way
System.Exit(0);
I added this only for info, but this might not work with multiple activities and this is not a good way for closing apps. It's mostly like the "Hold power button until the pc shuts down".
Clicking an element of another application on runtime is something that will be considered as a security threat. You would need a hack to go past this hurdle.
There is one hack that I recently found out, you can probably make use of it. You can find the source code here: https://github.com/tfKamran/android-ui-automator
You can add the code in here as a module in your app and invoke a service with action com.tf.uiautomator.ACTION_CLICK_ITEM and send the text of the element you want to click on as an extra with key itemText.
You can test it using adb like:
adb shell am startservice -a com.tf.uiautomator.ACTION_CLICK_ITEM -e itemText "OK"
I found one solution for force stop. After force stop how can i go back to my activity page ?
public class DeviceAccessibilityService extends AccessibilityService {
private static final String TAG = "litan";
private boolean isKilled = false;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
isKilled = false;
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event.getEventType()) {
AccessibilityNodeInfo nodeInfo = event.getSource();
Log.i(TAG, "ACC::onAccessibilityEvent: nodeInfo=" + nodeInfo);
if (nodeInfo == null) {
return;
}
List<AccessibilityNodeInfo> list = new ArrayList<>();
if ("com.android.settings.applications.InstalledAppDetailsTop".equals(event.getClassName())) {
if (Build.VERSION.SDK_INT >= 18) {
list = nodeInfo.findAccessibilityNodeInfosByViewId("com.android.settings:id/right_button");
} else if (Build.VERSION.SDK_INT >= 14) {
list = nodeInfo.findAccessibilityNodeInfosByText("com.android.settings:id/right_button");
}
for (AccessibilityNodeInfo node : list) {
Log.i(TAG, "ACC::onAccessibilityEvent: left_button " + node);
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
} else if ("android.app.AlertDialog".equals(event.getClassName())) {
list = new ArrayList<>();
if (Build.VERSION.SDK_INT >= 18) {
list = nodeInfo.findAccessibilityNodeInfosByViewId("android:id/button1");
} else if (Build.VERSION.SDK_INT >= 14) {
list = nodeInfo.findAccessibilityNodeInfosByText("android:id/button1");
}
for (final AccessibilityNodeInfo node : list) {
Log.i(TAG, "ACC::onAccessibilityEvent: button1 " + node);
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
//node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
return;
}
}
#Override
public void onInterrupt() {
// TODO Auto-generated method stub
Log.i("Interrupt", "Interrupt");
}
#Override
protected void onServiceConnected() {
AccessibilityServiceInfo info = getServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_WINDOWS_CHANGED | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.flags = AccessibilityServiceInfo.DEFAULT;
info.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
info.flags = AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY;
info.flags = AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
// We are keeping the timeout to 0 as we don’t need any delay or to pause our accessibility events
info.feedbackType = AccessibilityEvent.TYPES_ALL_MASK;
info.notificationTimeout = 100;
this.setServiceInfo(info);
// Toast.makeText(getApplicationContext(), "onServiceConnected", Toast.LENGTH_SHORT).show();
}
private static void logd(String msg) {
Log.d(TAG, msg);
}
private static void logw(String msg) {
Log.w(TAG, msg);
}
private static void logi(String msg) {
Log.i(TAG, msg);
}
}
Is there an onFinished listener of some sort? Or do we have to compare the current stream position against the duration of the track?
It's not pretty but you can make this call:
if (mRemoteMediaPlayer.getMediaStatus().getPlayerState() == MediaStatus.PLAYER_STATE_IDLE
&& mRemoteMediaPlayer.getMediaStatus().getIdleReason() == MediaStatus.IDLE_REASON_FINISHED) {
...
}
Prem,
There is currently no callback to register for such event. One alternative (and-not-so-pretty) approach is the following: on the receiver, listen for "ended" event of the media element and send an event back to the sender through a private channel. Another approach is what you suggested: check position against duration. When SDK graduates to general availability, better and cleaner approaches will be available to accomplish what you want.
Here is solution:
You just need to take one more variable mIdleReason.
1) Initialize mIdleReason as
public int mIdleReason=MediaStatus.IDLE_REASON_NONE;
2) Update value at method loadMedia
public void loadMedia(String url, MediaMetadata movieMetadata, CastSession castSession, boolean autoPlay, long position) {
if (castSession == null || !castSession.isConnected()) {
return;
}
MediaInfo mediaInfo = new MediaInfo.Builder(url)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType("videos/m3u8")
.setMetadata(movieMetadata)
.build();
mRemoteMediaClient = castSession.getRemoteMediaClient();
mRemoteMediaClient.addListener(mRemoteMediaClientListener);
mRemoteMediaClient.load(mediaInfo, autoPlay, position);
mIdleReason = MediaStatus.IDLE_REASON_NONE;
}
3) Update value at onStatusUpdate:
private RemoteMediaClient.Listener mRemoteMediaClientListener = new RemoteMediaClient.Listener() {
#Override
public void onStatusUpdated() {
if (mRemoteMediaClient == null || mediaPlayerListener == null) {
return;
}
MediaStatus mediaStatus = mRemoteMediaClient.getMediaStatus();
if (mediaStatus != null) {
int playerStatus = mediaStatus.getPlayerState();
Log.d("PlayerState", "onStatusUpdated() called, progress= "+mSeekBar.getProgress() +", stream duration= "+ mRemoteMediaClient.getStreamDuration()+" mSeekBar.getProgress() == mRemoteMediaClient.getStreamDuration()="+(mSeekBar.getProgress() == mRemoteMediaClient.getStreamDuration()));
Log.d("PlayerState", "onStatusUpdated() called playerStatus="+playerStatus+", idleReason="+mediaStatus.getIdleReason());
if (playerStatus == MediaStatus.PLAYER_STATE_PLAYING) {
mediaPlayerListener.playing();
mIdleReason = MediaStatus.IDLE_REASON_FINISHED;
} else if (playerStatus == MediaStatus.PLAYER_STATE_BUFFERING) {
mediaPlayerListener.buffering();
mIdleReason = MediaStatus.IDLE_REASON_FINISHED;
} else if (playerStatus == MediaStatus.PLAYER_STATE_PAUSED) {
mediaPlayerListener.paused();
} else if (playerStatus == MediaStatus.IDLE_REASON_INTERRUPTED) {
mediaPlayerListener.error();
} else if (playerStatus == MediaStatus.IDLE_REASON_ERROR) {
mediaPlayerListener.error();
}else if(playerStatus == MediaStatus.PLAYER_STATE_IDLE && mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_FINISHED&& mIdleReason == MediaStatus.IDLE_REASON_FINISHED){
mediaPlayerListener.played();
}
}
}
#Override
public void onMetadataUpdated() {
Log.d("", "onMetadataUpdated: ");
}
#Override
public void onQueueStatusUpdated() {
Log.d("", "onQueueStatusUpdated: ");
}
#Override
public void onPreloadStatusUpdated() {
Log.d("", "onPreloadStatusUpdated: ");
}
#Override
public void onSendingRemoteMediaRequest() {
Log.d("", "onSendingRemoteMediaRequest: ");
}
#Override
public void onAdBreakStatusUpdated() {
Log.d("", "onAdBreakStatusUpdated: ");
}
};
Is it possible to implement a fast forward button using the onLongClick button event?
EDIT
i used runnable inside the onlongclicklistner and adding the code for reference who needs :)
Button.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
final Runnable r = new Runnable()
{
public void run()
{//do the forwarding logic here
if(Button.isPressed()){
Button.postDelayed(this, 1000); //delayed for 1 sec
}else{
Button.postInvalidate();
Button.invalidate();
}
}
};
Button.post(r);
return true;
}
});
In your onLongClick event, set a member variable (example: mShouldFastForward) to true.
In the rest of your code (perhaps each frame played?) check if mShouldFastForward == true; if so, perform a fast-forward on that frame.
Use an onTouch event to capture the MotionEvent.ACTION_UP to set mShouldFastForward to false.
I have done it in this project (the project is not finished (ie polished) but fast forward works):
https://bitbucket.org/owentech/epileptic-gibbon-android
Take a look at playerfragment.java :
I handle this by using Threads to fast forward the mediaplayer.
Example code from project:
/*******************************/
/* Fast-Forward button actions */
/*******************************/
ffbutton.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent event) {
switch (event.getAction() ) {
case MotionEvent.ACTION_DOWN:
arrays.fastforwardpressed = true;
FastForwardThread newFFThread = new FastForwardThread();
arrays.fastforwardfrom = mp.getCurrentPosition();
arrays.fastforwardto = arrays.fastforwardfrom;
newFFThread.start();
break;
case MotionEvent.ACTION_UP:
arrays.fastforwardpressed = false;
mp.seekTo(arrays.fastforwardto);
break;
}
return true;
}
});
public class FastForwardThread extends Thread
{
public FastForwardThread()
{
super("FastForwardThread");
}
public void run()
{
while (arrays.fastforwardpressed == true)
{
arrays.fastforwardto = arrays.fastforwardto + 10000;
int fastforwardseconds = arrays.fastforwardto / 1000;
int hours = fastforwardseconds / 3600, remainder = fastforwardseconds % 3600, minutes = remainder / 60, seconds = remainder % 60;
String Hours = Integer.toString(hours);
String Minutes = Integer.toString(minutes);
String Seconds = Integer.toString(seconds);
if (Hours.length() == 1)
{
Hours = "0" + Hours;
}
if (Minutes.length() == 1)
{
Minutes = "0" + Minutes;
}
if (Seconds.length() == 1)
{
Seconds = "0" + Seconds;
}
arrays.formattedfftime = Hours + ":" + Minutes + ":" + Seconds;
fastforwardHandler.sendEmptyMessage(0);
try
{
sleep(100);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}