OK, so I have a much larger application that I am not actually going to post here. In it, there is a vibration event that is looped through, though technically it is not a while
loop [the event ends at the users request] and the values that make up the long[] pattern = {0,dot, gap, dash, gap, dot, gap, dot};
change at every iteration so setting vibrator.vibrate(pattern, 0);
is not an option.
I set up another application to test some things about Vibrator. I found that running a static pattern gave a desired output, but putting the onVibrate
method in a while loop basically destroyed any ability to recognized the signal. I didn't find any way for the system to know if the phone was currently vibrating only if it could vibrate. So I decided to nest onVibrate
behind a boolean that the method would ultimate control and that control would be a callback that would 'pause' for more than the length the pattern took up. It ended up looking like this:
public class MainActivity extends Activity {
Boolean im_vibrating;
CallBack mCallBack;
Vibrator vibrator;
interface MyCallBack {
void offSet(Integer span);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCallBack = new CallBack();
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
im_vibrating = false;
while (true) {
if (!im_vibrating) {
im_vibrating = true;
onVibrate();
}
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void onVibrate () {
int dot = 200;
int dash = 500;
int gap = 200;
long[] pattern = {
0,
dot, gap, dash, gap, dot, gap, dot
};
vibrator.vibrate(pattern, -1);
int span = dot + gap + dash + gap + dot + gap + dot + dot;
mCallBack.offSet(span);
}
class CallBack implements MyCallBack {
@Override
public void offSet(Integer span) {
final android.os.Handler handler = new android.os.Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
im_vibrating = false;
}
}, span);
}
}
}
However, despite having no errors, this doesn't work, something ends up blocking the rendering of the layout so the display is just blank, it vibrates once and then never again. Despite the fact that mCallBack
auto completed offSet
the SDK highlights offset
stating that it is never used.
OK taking into consideration what both parties above me said I ended up with this, which was exactly what I was looking for:
MainActivity.java
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Vibrator;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
Vibrator vibrator;
VibratePattern task;
Button stop_button;
Button start_button;
MyTaskParams params;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
stop_button = (Button) findViewById(R.id.button_stop);
stop_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
task.cancel(true);
task = null;
}
});
start_button = (Button) findViewById(R.id.button_start);
start_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (task == null) {
startTask();
}
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private static class MyTaskParams {
int dot, dash, gap;
MyTaskParams (int dot, int dash, int gap) {
this.dot = dot;
this.dash = dash;
this.gap = gap;
}
}
private void startTask() {
params = new MyTaskParams(200,500,200);
task = new VibratePattern();
task.execute(params);
}
public Integer onVibrate (Integer dot, Integer dash, Integer gap) {
long[] pattern = {
0,
dot, gap, dash, gap, dot, gap, dot
};
vibrator.vibrate(pattern, -1);
int span = dot + gap + dash + gap + dot + gap + dot + gap;
return span;
}
private class VibratePattern extends AsyncTask<MyTaskParams, Void, Integer> {
@Override
protected Integer doInBackground(MyTaskParams... params) {
int span;
span = onVibrate(params[0].dot,params[0].dash,params[0].gap);
return span;
}
@Override
protected void onPostExecute(Integer span) {
final android.os.Handler handler = new android.os.Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (!isCancelled()) {
startTask();
}
}
}, span);
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_start"
android:id="@+id/button_start"
android:layout_marginTop="90dp"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@+id/button_stop"
android:layout_toStartOf="@+id/button_stop" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_stop"
android:id="@+id/button_stop"
android:layout_alignTop="@+id/button_start"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="80dp"
android:layout_marginEnd="80dp" />
</RelativeLayout>
string.xml
<resources>
<string name="app_name">VibrationTest</string>
<string name="action_settings">Settings</string>
<string name="button_stop">Stop</string>
<string name="button_start">Start</string>
</resources>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="" >
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
startTask
could then load up new values every loop cycle dynamically changing the pulse as needed. Ty for your help.