I am looking for a way to allow my program to make the phone vibrate after the screen has turned off from timing out. I have done lots of research, and have not found something that works. I have looked at the PowerManager class and more specifically the WakeLock mechanism. From the sound of many posts, I would need to use the PARTIAL_WAKE_LOCK variable of the WakeLock class.
PARTIAL_WAKE_LOCK - Wake lock that ensures that the CPU is running.
However, I cannot get it to vibrate the phone when the screen turns off. I know I am using the WakeLock correctly because I can get SCREEN_DIM_WAKE_LOCK to work. Is PARTIAL_WAKE_LOCK what I am looking for?
#Override
public void onCreate() {
super.onCreate();
// REGISTER RECEIVER THAT HANDLES SCREEN ON AND SCREEN OFF LOGIC
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public void onStart(Intent intent, int startId) {
boolean screenOn = intent.getBooleanExtra("screen_state", false);
if (!screenOn) {
// Get instance of Vibrator from current Context
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
// This example will cause the phone to vibrate "SOS" in Morse Code
// In Morse Code, "s" = "dot-dot-dot", "o" = "dash-dash-dash"
// There are pauses to separate dots/dashes, letters, and words
// The following numbers represent millisecond lengths
int dot = 200; // Length of a Morse Code "dot" in milliseconds
int dash = 500; // Length of a Morse Code "dash" in milliseconds
int short_gap = 200; // Length of Gap Between dots/dashes
int medium_gap = 500; // Length of Gap Between Letters
int long_gap = 1000; // Length of Gap Between Words
long[] pattern = {
0, // Start immediately
dot, short_gap, dot, short_gap, dot, // s
medium_gap,
dash, short_gap, dash, short_gap, dash, // o
medium_gap,
dot, short_gap, dot, short_gap, dot, // s
long_gap
};
// Only perform this pattern one time (-1 means "do not repeat")
v.vibrate(pattern, -1);
} else {
// YOUR CODE
}
}
note u must Add the uses-permission line to your Manifest.xml file, outside of the block.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="...">
<uses-permission android:name="android.permission.VIBRATE"/>
note : you must also test this code on a real phone , emulator can't viberate
For me the solution was to use directly vibrate without patterns, so I don't have to use PowerManager to wake lock.
Related
I have an Android Wear watch face that I'm trying to have vibrate the watch on the hour. It is working except in cases where the watch screen is off. According to the log statements, the handler method is called every minute and the chime method is called on the hour. If I'm debugging over bluetooth with the Moto 360, it works even with the screen off. If I install a release apk, it only vibrates if the screen is on. If the screen is off at the top of the hour, it wont vibrate until the screen comes back on. I have tried acquiring a wake lock before the vibrate with no luck. I'm thinking it may work if I acquire a wake lock in the onCreate and release it in the onDestroy but I would rather not do that to preserve battery. Another interesting tidbit is that I have another function that vibrates when certain data changes in the wearable data api and that is working with the screen off. Maybe the WearableListenerService wakes the watch up long enough for the vibrate to occur. Is there something wrong with my logic or is this a limitation of certain Android Wear devices?
Time change handler:
final Handler mUpdateTimeHandler = new Handler() {
#Override
public void handleMessage(Message message) {
switch (message.what) {
case MSG_UPDATE_TIME:
MyLog.d("Time Tick Message Handler");
doTimeTickStuff();
long timeMs = System.currentTimeMillis();
long delayMs = mInteractiveUpdateRateMs - (timeMs % mInteractiveUpdateRateMs);
mUpdateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs);
break;
}
}
};
doTimeTickStuff()
private void doTimeTickStuff()
{
MyLog.d("timetickstuff");
try {
mCalendar = Calendar.getInstance();
int currMin = mCalendar.get(Calendar.MINUTE);
if (currMin == 0) {
hourlyChime();
}
}
catch(Exception ex)
{
MyLog.e(ex, "Error occurred in time tick handler");
}
if (mIsVisible) {
invalidate();
}
}
hourlyChime()
private void hourlyChime(){
Vibrator v = (Vibrator) getBaseContext().getSystemService(VIBRATOR_SERVICE);
if (v.hasVibrator()) {
MyLog.d("vibrating");
v.vibrate(1000);
}
else {
MyLog.d("No vibrator");
}
}
Update
The solution that worked was to create an AlarmManager and register it with a broadcast receiver in the watch face onCreate then unregister the receiver in onDestroy
onCreate()
#Override
public void onCreate(SurfaceHolder holder) {
super.onCreate(holder);
mChimeAlarmManager =
(AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent ambientStateIntent = new Intent("packagename.HOURLY_CHIME");
mChimePendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
1234, ambientStateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
WeatherTime.this.registerReceiver(chimeReceiver,
new IntentFilter("packagename.HOURLY_CHIME"));
long alarmMs = getMsTillNextHour() + System.currentTimeMillis();
mChimeAlarmManager.setExact(
AlarmManager.RTC_WAKEUP,
alarmMs,
mChimePendingIntent);
}
Broadcast Receiver
private BroadcastReceiver chimeReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent) {
hourlyChime();
mChimeAlarmManager.setExact(
AlarmManager.RTC_WAKEUP,
getMsTillNextHour() + System.currentTimeMillis(),
mChimePendingIntent);
}
};
onDestroy()
#Override
public void onDestroy() {
mChimeAlarmManager.cancel(mChimePendingIntent);
super.onDestroy();
}
When the watch goes into ambient mode, it goes into a deep sleep. As a result, code written with Handler will not run. As a result, you should use AlarmManager. For details on how to implement this, you should refer to the "Update more frequently" section on this page about the always-on functionality of Android Wear.
With regards to Bluetooth debug mode, I suspect that it works because the watch never goes into deep sleep. The same happens when I develop apps while the watch is docked.
Lastly, as for the wake up frequency, I think your functionality is fine as it only fires once an hour. For others reading this, please refrain from waking the watch up more than once a minute as this will severely impact battery life. Always test your watch face for battery life before uploading to the Play Store.
in my project i use Alarm manager with MyIntentService extends IntentService.
To wake up (on screen) device in onHandleIntent
use following:
if (intent.getAction() != null) {
tmp = intent.getAction();
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), TAG);
wakeLock.setReferenceCounted(true);
if(!wakeLock.isHeld()) {
wakeLock.acquire();
}
}
I need to enable and disable the vibration mode of mobile when user turns off and turns on the switch button .
I have tried the code below, but it's not working:
AudioManager myAudioManager;
myAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
Toast.makeText(this, "in setting "+(myAudioManager.getMode()==AudioManager.RINGER_MODE_VIBRATE),1).show();
if(myAudioManager.getMode()==AudioManager.RINGER_MODE_VIBRATE) {
//myAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
myAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_OFF);
}
else
{
//myAudioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
myAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_ON);
}
We can enable and disable the silent mode programmatically by using AudioManager:
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
for setting silent mode :
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
For normal mode :
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
First of all use this permission in AndroidManifest.xml
<uses-permission android:name="android.permission.VIBRATE"/>
Now
public void startVibrate(View v) {
long pattern[] = { 0, 100, 200, 300, 400 };
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(pattern, 0);
}
public void stopVibrate(View v) {
vibrator.cancel();
}
Vibrate pattern
public abstract void vibrate (long[] pattern, int repeat)
Pattern for vibration is nothing but an array of duration's to turn ON and OFF the vibrator in milliseconds. The first value indicates the number of milliseconds to wait before turning the vibrator ON. The next value indicates the number of milliseconds for which to keep the vibrator on before turning it off. Subsequent values, alternates between ON and OFF.
long pattern[]={0,100,200,300,400};
If you feel not to have repeats, just pass -1 for 'repeat'. To repeat patterns, just pass the index from where u wanted to start. I wanted to start from 0'th index and hence I am passing 0 to 'repeat'.
vibrator.vibrate(pattern, 0);
myAudioManager.setVibrateSetting();
This method was deprecated in API level 16.
you can use this one:
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT)
RINGER_MODE_SILENT : will mute the volume and will not vibrate.
RINGER_MODE_VIBRATE: will mute the volume and vibrate.
RINGER_MODE_NORMAL: will be audible and may vibrate according to user settings.
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
// Vibrate for 500 milliseconds
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
//deprecated in API 26
v.vibrate(500);
}
I want the device to start vibrating for some amount of time when screen timeout option enables(when the light dims, before the screen shuts off).I know how to set up both functions individually, but I can't seem to manage to get them in the right order for this to work, so I need your help. Thanks and cheers!
Use the vibrator class to initiate vibration
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
Vibrator vib = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
// Vibrate for 500 milliseconds
vib.vibrate(5);
}
}, 30000); //30 sec
Edit:
Don't forget as I did to declare in the app manifest file
<uses-permission android:name="android.permission.VIBRATE"/>
I have written a small test app (borrowed examples from previous implementation given in Stack Overflow) that will turn on Notification LED on my tablet . When I test this app on the tablet its not working as desired , i.e the LED turns on for a very small amount of time (and not for the 5 seconds duration that I have mentioned in my program). I guess its taking the system default value for the duration for which the LED needs to be ON/OFF rather than taking the value specified in my app. Has anyone seen a similar problem earlier ? Is there a way for me to override this system specific value ? My code is as below :
public class SampleActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
RedFlashLight();
}
private void RedFlashLight()
{
NotificationManager nm = ( NotificationManager ) getSystemService( NOTIFICATION_SERVICE );
Notification notif = new Notification();
notif.ledARGB = Color.RED;
notif.flags = Notification.FLAG_SHOW_LIGHTS ;
notif.ledOnMS = 5000; //5 seconds
notif.ledOffMS = 0; //do not turn it off
nm.notify(10, notif);
}
}
Is there a way for me to override this system specific value ?
Beyond what you are already doing? No.
Bear in mind:
Not all devices have LEDs
Not all devices that do have LEDs will necessarily use them for notifications
Device manufacturers can otherwise ignore the requests in the Notification object, such as LED color
So, you can ask for whatever you want, and whether you get it will depend on the device.
I am trying to turn on and off the display after a certain action happens (Lets just worry about turning the screen off for now). From what I understand from wake lock, this is what I have:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
When I read other posts on stackoverflow and else where, they seem to tell me that PARTIAL_WAKE_LOCK will turn the screen off. But if I read the SDK it says that it will only allow the screen to be turned off. I think this isn't right.
There are two choices for turning the screen off:
PowerManager manager = (PowerManager) getSystemService(Context.POWER_SERVICE);
// Choice 1
manager.goToSleep(int amountOfTime);
// Choice 2
PowerManager.WakeLock wl = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Your Tag");
wl.acquire();
wl.release();
You will probably need this permission too:
<uses-permission android:name="android.permission.WAKE_LOCK" />
UPDATE:
Try this method; android turns off the screen once the light level is low enough.
WindowManager.LayoutParams params = getWindow().getAttributes();
params.flags |= LayoutParams.FLAG_KEEP_SCREEN_ON;
params.screenBrightness = 0;
getWindow().setAttributes(params);
The following is copied from SDK document.
If you want to keep screen on, I think SCREEN_BRIGHT_WAKE_LOCK is enough.
Flag Value CPU Screen Keyboard
PARTIAL_WAKE_LOCK On* Off Off
SCREEN_DIM_WAKE_LOCK On Dim Off
SCREEN_BRIGHT_WAKE_LOCK On Bright Off
FULL_WAKE_LOCK On Bright Bright
For me those methods didn't work. So I used other scenario (not trivial) to make my screen off.
Android has 2 flags that responsible to be awake:
Display --> Screen TimeOut
Application --> Development --> Stay awake while charging check box.
I used followed flow:
1st of all save your previous configuration, for example screen timeout was 1 min and Stay awake while charging checked.
After, I uncheck Stay awake while charging and set screen timeout to minimal time.
I register to broadcast receiver service to get event from android that screen turned off.
When I got event on screen off, I set previous configuration to default: screen timeout was 1 min and Stay awake while charging checked.
Unregister receiver
After 15 sec. device sleeps
Here is snippets of code:
BroadcastReceiver
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
* Catch Screen On/Off
* */
public class BroadcastReceiverScreenListener extends BroadcastReceiver{
private BroadCastListenerCallBackItf mBroadCastListenerCallBack = null;
public BroadcastReceiverScreenListener(
BroadCastListenerCallBackItf broadCastListenerCallBack) {
this.mBroadCastListenerCallBack = broadCastListenerCallBack;
}
#Override
public void onReceive(Context arg0, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
mBroadCastListenerCallBack.broadCastListenerCallBack__ScreenOff_onResponse();
}
}
}
Interface used as callback
public interface BroadCastListenerCallBackItf {
public void broadCastListenerCallBack__ScreenOff_onResponse();
}
2 methods from main class:
....
AndroidSynchronize mSync = new AndroidSynchronize();
....
public void turnScreenOff(int wait){
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadCastListenerCallBackItf broadCastListenerCallBack = this;
BroadcastReceiver mReceiver = new BroadcastReceiverScreenListener(broadCastListenerCallBack);
m_context.registerReceiver(mReceiver, filter);
//set Development --> disable STAY_ON_WHILE_PLUGGED_IN
Settings.System.putInt(
m_context.getContentResolver(),
Settings.System.STAY_ON_WHILE_PLUGGED_IN,
0 );
// take current screen off time
int defTimeOut = Settings.System.getInt(m_context.getContentResolver(),
Settings.System.SCREEN_OFF_TIMEOUT, 3000);
// set 15 sec
Settings.System.putInt(m_context.getContentResolver(),
Settings.System.SCREEN_OFF_TIMEOUT, 15000);
// wait 200 sec till get response from BroadcastReceiver on Screen Off
mSync.doWait(wait*1000);
// set previous settings
Settings.System.putInt(m_context.getContentResolver(),
Settings.System.SCREEN_OFF_TIMEOUT, defTimeOut);
// switch back previous state
Settings.System.putInt(
m_context.getContentResolver(),
Settings.System.STAY_ON_WHILE_PLUGGED_IN,
BatteryManager.BATTERY_PLUGGED_USB);
m_context.unregisterReceiver(mReceiver);
}
public void broadCastListenerCallBack__ScreenOff_onResponse() {
mSync.doNotify();
}
....
AndroidSynchronize class
public class AndroidSynchronize {
public void doWait(long l){
synchronized(this){
try {
this.wait(l);
} catch(InterruptedException e) {
}
}
}
public void doNotify() {
synchronized(this) {
this.notify();
}
}
public void doWait() {
synchronized(this){
try {
this.wait();
} catch(InterruptedException e) {
}
}
}
}
[EDIT]
You need to register permission:
android.permission.WRITE_SETTINGS
Per this link, You can also turn the screen off like this:
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, 1000);
1000 is in milliseconds which means 1 second, you can replace it with any value as desired.
Needed permission:
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
try -
wakeLock.acquire(1000); // specify the time , it dims out and eventually turns off.