Browse Source

fixed #13

main
James Fenn 2 years ago
parent
commit
069e340ffc
8 changed files with 110 additions and 272 deletions
  1. +0
    -1
      wear/src/main/AndroidManifest.xml
  2. +97
    -76
      wear/src/main/java/james/metronome/MainActivity.java
  3. +0
    -195
      wear/src/main/java/james/metronome/MetronomeService.java
  4. +13
    -0
      wear/src/main/java/james/metronome/Utils.java
  5. BIN
      wear/src/main/res/drawable-hdpi/ic_notification.png
  6. BIN
      wear/src/main/res/drawable-mdpi/ic_notification.png
  7. BIN
      wear/src/main/res/drawable-xhdpi/ic_notification.png
  8. BIN
      wear/src/main/res/drawable-xxhdpi/ic_notification.png

+ 0
- 1
wear/src/main/AndroidManifest.xml View File

@@ -31,7 +31,6 @@
</intent-filter>
</activity>

<service android:name=".MetronomeService" />
</application>

</manifest>

+ 97
- 76
wear/src/main/java/james/metronome/MainActivity.java View File

@@ -1,12 +1,18 @@
package james.metronome;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Handler;
import android.os.PowerManager;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.support.wearable.activity.WearableActivity;
import android.support.wearable.view.BoxInsetLayout;
import android.view.View;
@@ -16,7 +22,10 @@ import android.widget.TextView;

import java.util.Locale;

public class MainActivity extends WearableActivity implements ServiceConnection, MetronomeService.TickListener {
public class MainActivity extends WearableActivity implements Runnable {

public static final String PREF_VIBRATION = "vibration";
public static final String PREF_INTERVAL = "interval";

private BoxInsetLayout container;
private ImageView vibrationView;
@@ -24,8 +33,19 @@ public class MainActivity extends WearableActivity implements ServiceConnection,
private TextView bpmView;
private SeekBar seekBar;

private MetronomeService service;
private boolean isBound;
private PowerManager.WakeLock wakeLock;

private SharedPreferences prefs;
private int bpm;
private long interval;

private SoundPool soundPool;
private Handler handler;
private int soundId = -1;
private boolean isPlaying;
private boolean isVibration;

private Vibrator vibrator;

@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -33,34 +53,69 @@ public class MainActivity extends WearableActivity implements ServiceConnection,
setContentView(R.layout.activity_main);
setAmbientEnabled();

PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
if (powerManager != null) {
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "idiot.metronome.MainActivity");
wakeLock.acquire();
}

prefs = PreferenceManager.getDefaultSharedPreferences(this);

vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
soundPool = new SoundPool.Builder()
.setMaxStreams(1)
.setAudioAttributes(new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build())
.build();
} else soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);

isVibration = prefs.getBoolean(PREF_VIBRATION, true);
if (!isVibration)
soundId = soundPool.load(this, R.raw.click, 1);

interval = prefs.getLong(PREF_INTERVAL, 500);
bpm = Utils.toBpm(interval);

handler = new Handler();

container = findViewById(R.id.container);
vibrationView = findViewById(R.id.vibration);
playView = findViewById(R.id.play);
bpmView = findViewById(R.id.bpm);
seekBar = findViewById(R.id.seekBar);

if (isBound()) {
vibrationView.setImageResource(service.isVibration() ? R.drawable.ic_vibration : R.drawable.ic_sound);
playView.setImageResource(service.isPlaying() ? R.drawable.ic_pause : R.drawable.ic_play);
bpmView.setText(String.format(Locale.getDefault(), getString(R.string.bpm), String.valueOf(service.getBpm())));
seekBar.setProgress(service.getBpm());
}
vibrationView.setImageResource(isVibration ? R.drawable.ic_vibration : R.drawable.ic_sound);
playView.setImageResource(isPlaying ? R.drawable.ic_pause : R.drawable.ic_play);
bpmView.setText(String.format(Locale.getDefault(), getString(R.string.bpm), String.valueOf(bpm)));
seekBar.setProgress(bpm);

vibrationView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
service.setVibration(!service.isVibration());
vibrationView.setImageResource(service.isVibration() ? R.drawable.ic_vibration : R.drawable.ic_sound);
isVibration = !isVibration;
prefs.edit().putBoolean(PREF_VIBRATION, isVibration).apply();

if (!isVibration)
soundId = soundPool.load(MainActivity.this, R.raw.click, 1);
else soundId = -1;

vibrationView.setImageResource(isVibration ? R.drawable.ic_vibration : R.drawable.ic_sound);
}
});

playView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (isBound()) {
if (service.isPlaying())
service.pause();
else service.play();
isPlaying = !isPlaying;
if (isPlaying) {
handler.post(MainActivity.this);
playView.setImageResource(R.drawable.ic_pause);
} else {
handler.removeCallbacks(MainActivity.this);
playView.setImageResource(R.drawable.ic_play);
}
}
});
@@ -68,7 +123,10 @@ public class MainActivity extends WearableActivity implements ServiceConnection,
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
setBpm(i);
bpm = i;
interval = Utils.toInterval(bpm);
bpmView.setText(String.format(Locale.getDefault(), getString(R.string.bpm), String.valueOf(bpm)));
prefs.edit().putLong(PREF_INTERVAL, interval).apply();
}

@Override
@@ -83,15 +141,18 @@ public class MainActivity extends WearableActivity implements ServiceConnection,
});
}

private void setBpm(int bpm) {
if (isBound()) {
service.setBpm(bpm);
bpmView.setText(String.format(Locale.getDefault(), getString(R.string.bpm), String.valueOf(bpm)));
}
@Override
protected void onPause() {
super.onPause();
isPlaying = false;
}

private boolean isBound() {
return isBound && service != null;
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(this);
if (wakeLock != null)
wakeLock.release();
}

@Override
@@ -119,55 +180,15 @@ public class MainActivity extends WearableActivity implements ServiceConnection,
}

@Override
protected void onStart() {
Intent intent = new Intent(this, MetronomeService.class);
startService(intent);
bindService(intent, this, Context.BIND_AUTO_CREATE);

super.onStart();
}

@Override
protected void onStop() {
if (isBound) {
unbindService(this);
isBound = false;
public void run() {
if (isPlaying) {
handler.postDelayed(this, interval);

if (soundId != -1)
soundPool.play(soundId, 1.0f, 1.0f, 0, 0, 1.0f);
else if (Build.VERSION.SDK_INT >= 26)
vibrator.vibrate(VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE));
else vibrator.vibrate(50);
}
super.onStop();
}

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
MetronomeService.LocalBinder binder = (MetronomeService.LocalBinder) iBinder;
service = binder.getService();
service.setTickListener(this);
isBound = true;

if (vibrationView != null)
vibrationView.setImageResource(service.isVibration() ? R.drawable.ic_vibration : R.drawable.ic_sound);

if (playView != null)
playView.setImageResource(service.isPlaying() ? R.drawable.ic_pause : R.drawable.ic_play);

if (bpmView != null)
bpmView.setText(String.format(Locale.getDefault(), getString(R.string.bpm), String.valueOf(service.getBpm())));

if (seekBar != null)
seekBar.setProgress(service.getBpm());
}

@Override
public void onServiceDisconnected(ComponentName componentName) {
isBound = false;
}

@Override
public void onStartTicks() {
playView.setImageResource(R.drawable.ic_pause);
}

@Override
public void onStopTicks() {
playView.setImageResource(R.drawable.ic_play);
}
}

+ 0
- 195
wear/src/main/java/james/metronome/MetronomeService.java View File

@@ -1,195 +0,0 @@
package james.metronome;

import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;

public class MetronomeService extends Service implements Runnable {

public static final String ACTION_PAUSE = "james.metronome.ACTION_PAUSE";

public static final String PREF_VIBRATION = "vibration";
public static final String PREF_INTERVAL = "interval";

private final IBinder binder = new LocalBinder();

private SharedPreferences prefs;
private int bpm;
private long interval;

private SoundPool soundPool;
private Handler handler;
private int soundId = -1;
private boolean isPlaying;
private boolean isVibration;

private Vibrator vibrator;

private TickListener listener;

@Override
public void onCreate() {
super.onCreate();
prefs = PreferenceManager.getDefaultSharedPreferences(this);

vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
soundPool = new SoundPool.Builder()
.setMaxStreams(1)
.setAudioAttributes(new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build())
.build();
} else soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);

isVibration = prefs.getBoolean(PREF_VIBRATION, true);
if (!isVibration)
soundId = soundPool.load(this, R.raw.click, 1);

interval = prefs.getLong(PREF_INTERVAL, 500);
bpm = toBpm(interval);

handler = new Handler();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.getAction() != null) {
switch (intent.getAction()) {
case ACTION_PAUSE:
pause();
}
}
return START_STICKY;
}

private static int toBpm(long interval) {
return (int) (60000 / interval);
}

private static long toInterval(int bpm) {
return (long) 60000 / bpm;
}

public void play() {
handler.post(this);
isPlaying = true;

Intent intent = new Intent(this, MetronomeService.class);
intent.setAction(ACTION_PAUSE);

startForeground(530,
new NotificationCompat.Builder(this)
.setContentTitle(getString(R.string.notification_title))
.setContentText(getString(R.string.notification_desc))
.setSmallIcon(R.drawable.ic_notification)
.setContentIntent(PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_ONE_SHOT))
.build()
);

if (listener != null)
listener.onStartTicks();
}

public void pause() {
handler.removeCallbacks(this);
stopForeground(true);
isPlaying = false;

if (listener != null)
listener.onStopTicks();
}

public void setBpm(int bpm) {
this.bpm = bpm;
interval = toInterval(bpm);
prefs.edit().putLong(PREF_INTERVAL, interval).apply();
}

public void setVibration(boolean vibration) {
isVibration = vibration;
if (!isVibration)
soundId = soundPool.load(this, R.raw.click, 1);
else soundId = -1;

prefs.edit().putBoolean(PREF_VIBRATION, isVibration).apply();
}

public boolean isPlaying() {
return isPlaying;
}

public long getInterval() {
return interval;
}

public int getBpm() {
return bpm;
}

public boolean isVibration() {
return isVibration;
}

public void setTickListener(TickListener listener) {
this.listener = listener;
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}

@Override
public boolean onUnbind(Intent intent) {
listener = null;
return super.onUnbind(intent);
}

@Override
public void onDestroy() {
handler.removeCallbacks(this);
super.onDestroy();
}

@Override
public void run() {
if (isPlaying) {
if (soundId != -1)
soundPool.play(soundId, 1.0f, 1.0f, 0, 0, 1.0f);
else if (Build.VERSION.SDK_INT >= 26)
vibrator.vibrate(VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE));
else vibrator.vibrate(50);

handler.postDelayed(this, interval);
}
}

public class LocalBinder extends Binder {
public MetronomeService getService() {
return MetronomeService.this;
}
}

public interface TickListener {
void onStartTicks();

void onStopTicks();
}
}

+ 13
- 0
wear/src/main/java/james/metronome/Utils.java View File

@@ -0,0 +1,13 @@
package james.metronome;

public class Utils {

public static int toBpm(long interval) {
return (int) (60000 / interval);
}

public static long toInterval(int bpm) {
return (long) 60000 / bpm;
}

}

BIN
wear/src/main/res/drawable-hdpi/ic_notification.png View File

Before After
Width: 36  |  Height: 36  |  Size: 568 B

BIN
wear/src/main/res/drawable-mdpi/ic_notification.png View File

Before After
Width: 24  |  Height: 24  |  Size: 364 B

BIN
wear/src/main/res/drawable-xhdpi/ic_notification.png View File

Before After
Width: 48  |  Height: 48  |  Size: 806 B

BIN
wear/src/main/res/drawable-xxhdpi/ic_notification.png View File

Before After
Width: 72  |  Height: 72  |  Size: 1.2 KiB

Loading…
Cancel
Save