Skip to content

Commit

Permalink
Fix naXa777#35 Prevent mis-clicks on buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
naXa777 committed Sep 8, 2018
1 parent 21dc22b commit b8e5b58
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 24 deletions.
4 changes: 2 additions & 2 deletions SoundRecorder.iml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
14 changes: 7 additions & 7 deletions app/app.iml
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,12 @@
<orderEntry type="library" name="Gradle: androidx.collection:collection:1.0.0-rc02@jar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: com.squareup:javawriter:2.1.1@jar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: androidx.test.espresso:espresso-idling-resource:3.1.0-alpha4@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.material:material:1.0.0-rc01@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.material:material:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.documentfile:documentfile:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.legacy:legacy-support-core-utils:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.print:print:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: org.jetbrains.trove4j:trove4j:20160824@jar" level="project" />
<orderEntry type="library" name="Gradle: com.crashlytics.sdk.android:crashlytics-core:2.6.3@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.recyclerview:recyclerview:1.0.0-rc01@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.appcompat:appcompat:1.0.0-rc01@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.versionedparcelable:versionedparcelable:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: com.squareup.leakcanary:leakcanary-watcher:1.6.1@jar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-common:2.0.0-rc01@jar" level="project" />
Expand All @@ -157,32 +155,34 @@
<orderEntry type="library" name="Gradle: androidx.customview:customview:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.slidingpanelayout:slidingpanelayout:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.core:core:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.vectordrawable:vectordrawable-animated:1.0.0-rc01@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.appcompat:appcompat:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-livedata-core:2.0.0-rc01@aar" level="project" />
<orderEntry type="library" name="Gradle: com.squareup.leakcanary:leakcanary-android:1.6.1@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: androidx.test:runner:1.1.0-alpha4@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: androidx.test.espresso:espresso-core:3.1.0-alpha4@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.transition:transition:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-runtime:2.0.0-rc01@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.vectordrawable:vectordrawable-animated:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: com.budiyev.android:circular-progress-bar:1.2.0@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: net.sf.kxml:kxml2:2.3.0@jar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: androidx.test:rules:1.1.0-alpha4@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.fragment:fragment:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.transition:transition:1.0.0-rc01@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.coordinatorlayout:coordinatorlayout:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: com.crashlytics.sdk.android:beta:1.2.9@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.recyclerview:recyclerview:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.legacy:legacy-support-core-ui:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: com.googlecode.mp4parser:isoparser:1.1.22@jar" level="project" />
<orderEntry type="library" name="Gradle: androidx.vectordrawable:vectordrawable:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: io.fabric.sdk.android:fabric:1.4.3@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.swiperefreshlayout:swiperefreshlayout:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.cardview:cardview:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: com.google.code.findbugs:jsr305:2.0.1@jar" level="project" />
<orderEntry type="library" name="Gradle: com.crashlytics.sdk.android:answers:1.4.2@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.viewpager:viewpager:1.0.0-rc02@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12@jar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3@jar" level="project" />
<orderEntry type="library" name="Gradle: androidx.cardview:cardview:1.0.0-rc01@aar" level="project" />
<orderEntry type="library" name="Gradle: com.squareup.leakcanary:leakcanary-analyzer:1.6.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.crashlytics.sdk.android:crashlytics:2.9.4@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.vectordrawable:vectordrawable:1.0.0-rc01@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.arch.core:core-runtime:2.0.0-rc01@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-integration:1.3@jar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-library:1.3@jar" level="project" />
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/by/naxa/soundrecorder/RecorderState.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

public enum RecorderState {
STOPPED,
PREPARING,
RECORDING,
PAUSED
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import by.naxa.soundrecorder.R;
import by.naxa.soundrecorder.RecordingItem;
import by.naxa.soundrecorder.listeners.HeadsetListener;
import by.naxa.soundrecorder.listeners.OnSingleClickListener;
import by.naxa.soundrecorder.util.AudioManagerCompat;
import by.naxa.soundrecorder.util.EventBroadcaster;
import by.naxa.soundrecorder.util.ScreenLock;
Expand Down Expand Up @@ -186,9 +187,9 @@ public void onStopTrackingTouch(SeekBar seekBar) {
attachHeadsetListener();

mPlayButton = view.findViewById(R.id.fab_play);
mPlayButton.setOnClickListener(new View.OnClickListener() {
mPlayButton.setOnClickListener(new OnSingleClickListener() {
@Override
public void onClick(View v) {
public void onSingleClick(View v) {
isPlaying = onPlay(isPlaying);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import by.naxa.soundrecorder.R;
import by.naxa.soundrecorder.RecorderState;
import by.naxa.soundrecorder.listeners.OnSingleClickListener;
import by.naxa.soundrecorder.services.RecordingService;
import by.naxa.soundrecorder.util.Command;
import by.naxa.soundrecorder.util.EventBroadcaster;
Expand Down Expand Up @@ -146,9 +147,9 @@ public void onChronometerTick(Chronometer chronometer) {
};

private View.OnClickListener createPauseButtonClickListener() {
return new View.OnClickListener() {
return new OnSingleClickListener() {
@Override
public void onClick(View v) {
public void onSingleClick(View v) {
if (isPauseButtonInState1) {
// pause recording
mRecordingService.pauseRecording();
Expand All @@ -166,9 +167,9 @@ public void onClick(View v) {
}

private View.OnClickListener createRecordButtonClickListener() {
return new View.OnClickListener() {
return new OnSingleClickListener() {
@Override
public void onClick(View v) {
public void onSingleClick(View v) {
if (isRecordButtonInState1) {
if (PermissionsHelper.checkAndRequestPermissions(
RecordFragment.this, MY_PERMISSIONS_REQUEST_RECORD_AUDIO)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package by.naxa.soundrecorder.listeners;

import android.os.SystemClock;
import android.view.View;

/**
* Mis-clicking prevention, using threshold of 600 ms
* Source: https://stackoverflow.com/a/20672997/1429387
*
* 处理快速在某个控件上双击2次(或多次)会导致onClick被触发2次(或多次)的问题
* 通过判断2次click事件的时间间隔进行过滤
* <p>
* 子类通过实现{@link #onSingleClick}响应click事件
*/
public abstract class OnSingleClickListener implements View.OnClickListener {
/**
* 最短click事件的时间间隔
*/
private static final long MIN_CLICK_INTERVAL = 600;
/**
* 上次click的时间
*/
private long mLastClickTime;

/**
* click响应函数
*
* @param v The view that was clicked.
*/
public abstract void onSingleClick(View v);

@Override
public final void onClick(View v) {
long currentClickTime = SystemClock.uptimeMillis();
long elapsedTime = currentClickTime - mLastClickTime;

if (elapsedTime <= MIN_CLICK_INTERVAL)
return;
mLastClickTime = currentClickTime;

onSingleClick(v);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,9 @@ public void setFileNameAndPath(boolean isFilePathTemp) {
* Start or resume sound recording.
*/
public void startRecording() {
if (state == RecorderState.RECORDING)
if (state == RecorderState.RECORDING || state == RecorderState.PREPARING)
return;
state = RecorderState.PREPARING;

boolean isTemporary = true;
setFileNameAndPath(isTemporary);
Expand All @@ -202,10 +203,12 @@ public void startRecording() {
Toast.makeText(this, R.string.toast_recording_start, Toast.LENGTH_SHORT).show();
mStartingTimeMillis = SystemClock.elapsedRealtime();
} catch (IOException e) {
state = RecorderState.STOPPED;
Crashlytics.logException(e);
Log.e(LOG_TAG, "prepare() failed", e);
EventBroadcaster.send(this, getString(R.string.error_unknown));
} catch (IllegalStateException e) {
state = RecorderState.STOPPED;
Crashlytics.logException(e);
Log.e(LOG_TAG, "start() failed", e);
EventBroadcaster.send(this, getString(R.string.error_mic_is_busy));
Expand All @@ -215,29 +218,40 @@ public void startRecording() {
public void pauseRecording() {
if (state != RecorderState.RECORDING)
return;
state = RecorderState.PREPARING;

mElapsedMillis = (SystemClock.elapsedRealtime() - mStartingTimeMillis);
pauseDurations.add(mElapsedMillis);
mRecorder.stop();
state = RecorderState.PAUSED;
Toast.makeText(this, getString(R.string.toast_recording_paused), Toast.LENGTH_LONG).show();
try {
mElapsedMillis = (SystemClock.elapsedRealtime() - mStartingTimeMillis);
pauseDurations.add(mElapsedMillis);
mRecorder.stop();
state = RecorderState.PAUSED;
Toast.makeText(this, getString(R.string.toast_recording_paused), Toast.LENGTH_LONG).show();

filesPaused.add(mFilePath);
filesPaused.add(mFilePath);
} catch (IllegalStateException exc) {
state = RecorderState.RECORDING;
Crashlytics.logException(exc);
Log.e(LOG_TAG, "stop() failed", exc);
}
}

public void stopRecording() {
if (state == RecorderState.STOPPED) {
Log.wtf(LOG_TAG, "stopRecording: already STOPPED.");
return;
}
if (state == RecorderState.RECORDING)
if (state == RecorderState.PREPARING)
return;
final RecorderState stateBefore = state;
state = RecorderState.PREPARING;
if (stateBefore == RecorderState.RECORDING)
filesPaused.add(mFilePath);

boolean isTemporary = false;
setFileNameAndPath(isTemporary);

try {
if (state != RecorderState.PAUSED) {
if (stateBefore != RecorderState.PAUSED) {
mElapsedMillis = (SystemClock.elapsedRealtime() - mStartingTimeMillis);
mRecorder.stop();
}
Expand Down

0 comments on commit b8e5b58

Please sign in to comment.