Android Wear OS application vibration sometimes doesn't work - android

I am developing an Android Wear OS 2.0 application. Every time a user gets an SMS from a given number, the watch should start vibrating, and a UI with a given text should appear, with a button, which stops the vibration. It works in the following way:
In the SmsReciever.java I'm checking if the phone number is matching, or the UI screen is already active.
public class SmsReceiver extends BroadcastReceiver {
//interface
private static SmsListener mListener;
#Override
public void onReceive(Context context, Intent intent) {
Bundle data = intent.getExtras();
Object[] pdus = (Object[]) data.get("pdus");
for(int i=0;i<pdus.length;i++){
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i], "3gpp");
String sender = smsMessage.getDisplayOriginatingAddress();
String alertPhoneNumber = "301112233";
if (sender.toLowerCase().contains(alertPhoneNumber.toLowerCase()))
{
String messageBody = smsMessage.getMessageBody();
//Pass the message text to interface
mListener.messageReceived(messageBody);
} else if (AlarmActivity.active) {
Intent intent1 = new Intent();
intent1.setClassName("hu.asd.watchtest", "hu.asd.watchtest.AlarmActivity");
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
}
}
}
public static void bindListener(SmsListener listener) {
mListener = listener;
}
}
I have needed the else if part, because sometimes when the UI was active, and I've received a new message, the vibration stopped. So that part starts the AlarmActivity (which handles the vibrating).
In the MainActivity.java I'm binding a new listener, so now every time I get the right message in the SmsReciever, the AlarmActivity should run:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestPermissions(Manifest.permission.RECEIVE_SMS, PERMISSIONS_REQUEST_RECEIVE_SMS);
SmsReceiver.bindListener(new SmsListener() {
#Override
public void messageReceived(String messageText) {
Intent myIntent = new Intent(MainActivity.this, AlarmActivity.class);
MainActivity.this.startActivity(myIntent);
}
});
}
In the AlarmActivity.java the application wakes the screen up, then gets the Vibrator, sets the onClickListeners to the stop vibrating button, and then starts the actual vibration. I also change the active state here:
public class AlarmActivity extends WearableActivity {
static boolean active = false;
#Override
public void onResume() {
super.onResume();
active = true;
}
#Override
public void onStart() {
super.onStart();
active = true;
}
#Override
public void onStop() {
super.onStop();
active = false;
}
#Override
public void onPause() {
super.onPause();
active = false;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm);
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP|PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
"MyWakelockTag");
wakeLock.acquire();
findViewById(R.id.stop_button).getBackground().setLevel(5000);
final Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
final long[] mVibratePattern = new long[]{0, 400, 800, 600, 800, 800, 800, 1000};
final int[] mAmplitudes = new int[]{0, 255, 0, 255, 0, 255, 0, 255};
final Button stopButton = findViewById(R.id.stop_button);
stopButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
vibrator.cancel();
wakeLock.release();
new SendEmail().execute();
Intent myIntent = new Intent(AlarmActivity.this, MainActivity.class);
AlarmActivity.this.startActivity(myIntent);
}
});
setAmbientEnabled();
vibrator.vibrate(VibrationEffect.createWaveform(mVibratePattern, mAmplitudes, 0)); // 0 to repeat endlessly.
}
}
If the user presses the Button, then the MainActivity starts again. The problem is, that out of 50 cases, I can send multiple text messages, the watch will vibrate until I press the stop button, but in 1 case, it'll only vibrate once, then it will stop vibrating. It usually happens, if the AlarmActivity is active already and vibrating, or vibration was cancelled before. I'm guessing that I do way to much work with intents, or something with the Vibrator instances? Or when I get a new text, the watch requires the Vibrator, and my Application can't get it?
This is my first Android application, and I tried a lot of different implementations, but still not perfect.

Related

How to set limit when user enter wrong pattern many time?

Currentlly I am implementing pattern lock application and I want to set limit when user enter wrong pattern many time.Example,If user enter wrong pattern at that time set limit(3 or 4 time limit) and set delay 30 second and after 30 second give permission to enter pattern.
So,If anyone know how i can do this please give idea of that.
Here this my Reciever
public class LockScreenReceiver extends DeviceAdminReceiver {
Context context;
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("Action...","..."+action);
//If the screen was just turned on or it just booted up, start your Lock Activity
if(action.equals(Intent.ACTION_SCREEN_OFF) || action.equals(Intent.ACTION_BOOT_COMPLETED))
{
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
#Override
public void onPasswordFailed(Context ctxt, Intent intent) {
DevicePolicyManager mgr = (DevicePolicyManager) ctxt.getSystemService(Context.DEVICE_POLICY_SERVICE);
int no = mgr.getCurrentFailedPasswordAttempts();
if (no >= 3) {
context.startActivity(new Intent(context,ChangeActivity.class));
}
}
}
Service
public class LockScreenService extends Service {
DeviceAdminReceiver receiver;
#Override
public IBinder onBind(Intent intent) {
return null;
}
// Register for Lockscreen event intents
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
receiver = new LockScreenReceiver();
registerReceiver(receiver, filter);
startForeground();
return START_STICKY;
}
// Run service in foreground so it is less likely to be killed by system
private void startForeground() {
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(getResources().getString(R.string.app_name))
.setTicker(getResources().getString(R.string.app_name))
.setContentText("Running")
.setContentIntent(null)
.setOngoing(true)
.build();
startForeground(9999,notification);
}
#Override
#SuppressWarnings("deprecation")
public void onCreate() {
KeyguardManager.KeyguardLock key;
KeyguardManager km = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
//This is deprecated, but it is a simple way to disable the lockscreen in code
key = km.newKeyguardLock("IN");
key.disableKeyguard();
//Start listening for the Screen On, Screen Off, and Boot completed actions
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
//Set up a receiver to listen for the Intents in this Service
receiver = new LockScreenReceiver();
registerReceiver(receiver, filter);
super.onCreate();
}
#Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
}
Activity
public class MainActivity extends ActionBarActivity {
private Lock9View lock9View;
private static String MY_PREFS_NAME = "PatternLock";
private static String PATTERN_KEY;
SharedPreferences prefs;
Button btnChange;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(MainActivity.this, LockScreenService.class));
makeFullScreen();
setContentView(R.layout.activity_main);
btnChange = (Button)findViewById(R.id.btnChange);
btnChange.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent in = new Intent(MainActivity.this,ChangeActivity.class);
startActivity(in);
}
});
prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
lock9View = (Lock9View) findViewById(R.id.lock_9_view);
lock9View.setCallBack(new Lock9View.CallBack() {
#Override
public void onFinish(String password) {
PATTERN_KEY = prefs.getString("Pattern", "invalid");
if (PATTERN_KEY.equals("invalid")) {
Toast.makeText(MainActivity.this, "Options --> Create new Pattern", Toast.LENGTH_LONG).show();
} else {
if (password.equals(PATTERN_KEY)) {
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
}else{
Context context = getApplicationContext();
// Create layout inflator object to inflate toast.xml file
LayoutInflater inflater = getLayoutInflater();
// Call toast.xml file for toast layout
View toastRoot = inflater.inflate(R.layout.layout_toast3, null);
Toast toast = new Toast(context);
// Set layout to toast
toast.setView(toastRoot);
toast.setGravity(Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.BOTTOM,
0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.show();
}
}
}
});
}
private void makeFullScreen() {
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
if(Build.VERSION.SDK_INT < 19) { //View.SYSTEM_UI_FLAG_IMMERSIVE is only on API 19+
this.getWindow().getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
} else {
this.getWindow().getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE);
}
}
#Override
public void onBackPressed() {
return; //Do nothing!
}
public void unlockScreen(View view) {
//Instead of using finish(), this totally destroys the process
android.os.Process.killProcess(android.os.Process.myPid());
}
}
So,How i can achieve this...
Have a int field like failedCounter and increment it each time user inputs invalid patterns check if reached the limit then disable the input interface and have a handler to reset the value after the time delay.
int failedCount = 0;
final static int LIMIT = 5; //set your limit here
private void invalidPattern() {
if (++failedCount == LIMIT) {
//disable the input
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//reset the failed count
faildCount = 0;
//Enable the input interface here
}
}, 30000); // 30Sec delay
}
}
Use this two methods -
ScheduledThreadPoolExecutor c1;
private void IncorrectCallCounter() {
if (failedCounter>=0)
{
c1.shutdownNow();
LockScreenFor30Second();
}else
{
if (c1!=null)
c1.shutdownNow();
}
c1 = new ScheduledThreadPoolExecutor(1);
c1.schedule(new Runnable() {
#Override
public void run() {
failedCounter=0;
c1.shutdownNow();
}
}, 15, TimeUnit.SECONDS);
}
ScheduledThreadPoolExecutor c2;
private void LockScreenFor30Second() {
//Lock Screen Here
c2 = new ScheduledThreadPoolExecutor(1);
c2.schedule(new Runnable() {
#Override
public void run() {
//Unlock Screen Here
c2.shutdownNow();
}
}, 30, TimeUnit.SECONDS);
}
Declare failedCounter globally
private int failedCounter=0;
And call this method when you detect wrong pattern -
failedCounter=failedCounter+1;
IncorrectCallCounter();
If user enter wrong pattern 4 times in 15 seconds then this will call LockScreenFor30Second method. and inside LockScreenFor30Second add your code.

Broadcast receiver is not working when app on foreground or active

I am building app regarding battery indicator and i am using code from this post.
Getting battery status even when the application is closed
it is working fine when app is closed, but when an app is active or on foreground it did not work or did not send any broadcast.
This is main activity from i start service
public class Main extends Activity {
private MyService service;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (service == null) {
Intent i = new Intent(this, MyService.class);
startService(i);
}
finish();
}
}
Following is the service code.
public class MyService extends Service{
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "onStartCommand");
// do not receive all available system information (it is a filter!)
final IntentFilter battChangeFilter = new IntentFilter(
Intent.ACTION_BATTERY_CHANGED);
// register our receiver
this.registerReceiver(this.batteryChangeReceiver, battChangeFilter);
return super.onStartCommand(intent, flags, startId);
}
private final BroadcastReceiver batteryChangeReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
checkBatteryLevel(intent);
}
};
private void checkBatteryLevel(Intent batteryChangeIntent) {
// some calculations
final int currLevel = batteryChangeIntent.getIntExtra(
BatteryManager.EXTRA_LEVEL, -1);
final int maxLevel = batteryChangeIntent.getIntExtra(
BatteryManager.EXTRA_SCALE, -1);
final int percentage = (int) Math.round((currLevel * 100.0) / maxLevel);
if(percentage==100)
{
Intent intent = new Intent(getBaseContext(), Last.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(intent);
}
// do not forget to unregister
unregisterReceiver(batteryChangeReceiver);
} }
And when following activity start i did not receive any broadcast.
public class Last extends Activity {
Button btnCancel;
Uri notification;
Ringtone r;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_last);
notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
btnCancel = (Button) findViewById(R.id.stopsound);
btnCancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
r.stop();
}
});
} }
As I understood,
when you start application in first time, you see nothing, just service is started and a broadcast receiver is registered. When battery level will be changed, the method checkBatteryLevel() is calling and the broadcast receiver will be unregistered. As result you have never received a new changing of battery level.

How to create an alarm wake screen in android and disable default back button?

Hello every one I request you to please give me the solution of this question .
I have created a alarm wake up screen when alarm started it has two buttons snooze and dismiss and it work fine .
But the problem is started when user press the back button on phone it disappears from the screen
and sound is still playing. If anyone have solution please provide me.
Thank you
This is AlarmService class
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class AlarmService extends Service {
public static String TAG = AlarmService.class.getSimpleName();
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent alarmIntent = new Intent(getBaseContext(), AlarmScreen.class);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try{
alarmIntent.putExtras(intent);
getApplication().startActivity(alarmIntent);
AlarmManagerHelper.setAlarms(this);
}catch(Exception e)
{
e.printStackTrace();
System.out.println(" May be null intent found if not snooz or dismiss the button by user on alarm screen");
}
return super.onStartCommand(intent, flags, startId);
}
}
and this one is receiver class that create an alarm screen
public class AlarmScreen extends Activity{
public final String TAG = this.getClass().getSimpleName();
private WakeLock mWakeLock;
private MediaPlayer mPlayer;
public static final String ID = "id";
public static final String NAME = "name";
public static final String TIME_HOUR = "timeHour";
public static final String TIME_MINUTE = "timeMinute";
public static final String TONE = "alarmTone";
public static final String NOTE = "note";
public static final String USER = "user";
static String name;
static String note;
static String userName;
static String tone;
static int timeHour;
static int timeMinute;
private static final int WAKELOCK_TIMEOUT = 60 * 1000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Setup layout
this.setContentView(R.layout.activity_alarm_screen);
/*parentView.getBackground().setAlpha(128);*/
name = getIntent().getStringExtra(AlarmManagerHelper.NAME);
note = getIntent().getStringExtra(AlarmManagerHelper.NOTE);
userName = getIntent().getStringExtra(AlarmManagerHelper.USER);
timeHour = getIntent().getIntExtra(AlarmManagerHelper.TIME_HOUR, 0);
timeMinute = getIntent().getIntExtra(AlarmManagerHelper.TIME_MINUTE, 0);
tone = getIntent().getStringExtra(AlarmManagerHelper.TONE);
TextView tvName = (TextView) findViewById(R.id.alarm_screen_name);
TextView tvNote = (TextView) findViewById(R.id.alarm_screen_note);
TextView tvUser = (TextView) findViewById(R.id.txt_nameUser);
tvName.setText(name);
tvNote.setText(note);
tvUser.setText(userName);
TextView tvTime = (TextView) findViewById(R.id.alarm_screen_time);
tvTime.setText(String.format("%02d : %02d", timeHour, timeMinute));
DisplayMetrics metrics = getResources().getDisplayMetrics();
final int screenWidth = (int) (metrics.widthPixels * 0.50);
final int screenHeight = (int) (metrics.heightPixels * 0.50);
// Get instance of Vibrator from current Context
final Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
// Start without a delay
// Each element then alternates between vibrate, sleep, vibrate, sleep...
long[] pattern = {0,800,200,1000,300,1000,200,4000};
if (v.hasVibrator()) {
Log.v("Can Vibrate", "YES");
} else {
Log.v("Can Vibrate", "NO");
}
Button dismissButton = (Button) findViewById(R.id.alarm_screen_button);
dismissButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
mPlayer.stop();
v.cancel();
finish();
}
});
//adding snooz button
Button btn_snooz = (Button) findViewById(R.id.btn_snooz);
btn_snooz.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
mPlayer.stop();
v.cancel();
sooz_activity();
System.out.println("Snooz Activity Started");
finish();
}
});
//Play alarm tone
mPlayer = new MediaPlayer();
try {
if (tone != null && !tone.equals("")) {
Uri toneUri = Uri.parse(tone);
if (toneUri != null) {
mPlayer.setDataSource(this, toneUri);
mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mPlayer.setLooping(true);
mPlayer.prepare();
mPlayer.start();
v.vibrate(pattern, 0);
}
}
} catch (Exception e) {
e.printStackTrace();
}
//Ensure wakelock release
Runnable releaseWakelock = new Runnable() {
#Override
public void run() {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
// getWindow().setLayout(screenWidth, screenHeight);
/* getWindow().setFlags(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT);*/
if (mWakeLock != null && mWakeLock.isHeld()) {
mWakeLock.release();
}
}
};
new Handler().postDelayed(releaseWakelock, WAKELOCK_TIMEOUT);
}
#SuppressWarnings("deprecation")
#Override
protected void onResume() {
super.onResume();
// Set the window to keep screen on
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
// getWindow().setLayout(screenWidth, screenHeight);
// Acquire wakelock
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
if (mWakeLock == null) {
mWakeLock = pm.newWakeLock((PowerManager.FULL_WAKE_LOCK | PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), TAG);
}
if (!mWakeLock.isHeld()) {
mWakeLock.acquire();
Log.i(TAG, "Wakelock aquired!!");
}
}
#Override
protected void onPause() {
super.onPause();
if (mWakeLock != null && mWakeLock.isHeld()) {
mWakeLock.release();
}
}
public void sooz_activity(){
PendingIntent pIntent = createPendingIntent(this);
long currentTimeMillis = System.currentTimeMillis();
long nextUpdateTimeMillis = currentTimeMillis + 5 * DateUtils.MINUTE_IN_MILLIS;
Time nextUpdateTime = new Time();
nextUpdateTime.set(nextUpdateTimeMillis);
setAlarm(this, nextUpdateTimeMillis, pIntent);
}
private static PendingIntent createPendingIntent(Context context) {
Intent intent = new Intent(context, AlarmService.class);
//intent.putExtra(ID, model.id);
intent.putExtra(NAME,name);
intent.putExtra(TIME_HOUR,timeHour);
intent.putExtra(TIME_MINUTE,timeMinute);
intent.putExtra(TONE,tone);
intent.putExtra(NOTE,note);
intent.putExtra(USER,userName);
return PendingIntent.getService(context,1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
#SuppressLint("NewApi")
private static void setAlarm(Context context, long nextUpdateTimeMillis, PendingIntent pIntent) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, nextUpdateTimeMillis, pIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, nextUpdateTimeMillis, pIntent);
}
}
}
and it works fine but when alarm screen appears on the phone main screen and user just pressed the default phone back button it disappear from the main screen and the sound and vibration continue until i go to stop running task.
All you got to do is override onBackPressed().
Android studio autocompletes this code as you type onBackPressed().
#Override
public void onBackPressed() // Declare in the activity showing the alarm screen
{
// code here what should be done at back button press
super.onBackPressed(); // This line handles the default action of back button
}
Before super.onBackPressed(), you may do something like snooze or something.
Also you can use onPause() or similar ones as the other guy said. (Refer Activity lifecycle)
Hope I cleared your doubt. Let me know if you got further doubts.
I think "The New Boston" has a great video to help with understanding what is going on here.
https://www.youtube.com/watch?v=-G91Hp3t6sg
you might be looking for onPause() to stop the sound.
I think the video would be a good starting point for monitoring how your app is behaving in different states.

Broadcast receiver popup message in android

In my application i using a broadcastreceiver to receive a incoming call and shown a some details to user. It works fine, but when i opened the application and incoming call is received, it shows at top of application, not the top of incoming call screen. How to solve this issue ?
thanks in advance
Broadcast Receiver
public void onReceive(final Context context, final Intent intent) { // 1
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); // 2
if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) { // 3
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); // 4
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(context, Test1.class);
i.putExtras(intent);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(i);
}
}, 2000);
}
}
Message Showing Activity
public class Test1 extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.popup);
WindowManager.LayoutParams wmlp = getWindow().getAttributes();
wmlp.gravity = Gravity.BOTTOM | Gravity.LEFT;
String number = getIntent().getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
TextView tv1 = (TextView)findViewById(R.id.tv1);
tv1.setText(number);
TextView tv2 = (TextView)findViewById(R.id.tv2);
tv2.setText(MyApp.mDbh.check(number));
new Handler().postDelayed(new Runnable(){
public void run() {
finish();
}
}, 10 *1000);
}
}

Stop CPU from sleeping when screen is off

I have an app that runs a webview as a service so the audio can contiune to play while the screen is locked. The app works great with audio streams such as podcasts. But I also wanted it to work with flash video. I am able to load the flash video stream in the webview and have it play smooth and steady but once the screen goes off or is locked the audio becomes choppy. The behavior is the same on 3g and WiFi. I tried to use this posts suggestion of using a wake lock with:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Tag");
wl.acquire();
//do what you need to do
wl.release();
However this has no effect. I'm not sure where exactly in my code to put it but I've placed it in the oncreate for the service, which had no effect, and I placed it in the oncreate for my main activity with the same results.
However later in the post the person asking the question said that WIFI_MODE_FULL_HIGH_PERF was able to fix the problem. But as I said I tested it on 3g and the audio stuttered when the screen was turned off.
Any ideas how I can stop this behavior?
Also I know this is a CPU intensive and a battery hog app but I'm just developing it for personal use.
This is my full code for the service:
public class MyService extends Service {
private NotificationManager nm;
private static boolean isRunning = false;
ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
int mValue = 0; // Holds last value set by a client.
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
static final int MSG_SET_INT_VALUE = 3;
static final int MSG_SET_STRING_VALUE = 4;
PowerManager.WakeLock wl;
#Override
public IBinder onBind(Intent intent) {
wl.acquire();
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.i("MyService", "Service Started.");
showNotification();
isRunning = true;
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Tag");
}
private void showNotification() {
nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(R.string.service_started);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis());
notification.flags = Notification.FLAG_ONGOING_EVENT;
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent);
// Send the notification.
// We use a layout id because it is a unique number. We use it later to cancel.
nm.notify(R.string.service_started, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyService", "Received start id " + startId + ": " + intent);
return START_STICKY; // run until explicitly stopped.
}
public static boolean isRunning()
{
return isRunning;
}
#Override
public void onDestroy() {
super.onDestroy();
nm.cancelAll();
wl.release();
nm.cancel(R.string.service_started); // Cancel the persistent notification.
Log.i("MyService", "Service Stopped.");
isRunning = false;
}
}
My main code:
public class MainActivity extends Activity {
Button btnStart, btnStop, btnBind, btnUnbind, btnUpby1, btnUpby10;
Messenger mService = null;
boolean mIsBound;
WebView mWebView;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
try {
Message msg = Message.obtain(null, MyService.MSG_REGISTER_CLIENT);
mService.send(msg);
} catch (RemoteException e) {
// In this case the service has crashed before we could even do anything with it
}
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been unexpectedly disconnected - process crashed.
mService = null;
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnStart = (Button)findViewById(R.id.btnStart);
btnStop = (Button)findViewById(R.id.btnStop);
btnBind = (Button)findViewById(R.id.btnBind);
btnUnbind = (Button)findViewById(R.id.btnUnbind);
btnStart.setOnClickListener(btnStartListener);
btnStop.setOnClickListener(btnStopListener);
btnBind.setOnClickListener(btnBindListener);
CheckIfServiceIsRunning();
//webview
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setPluginsEnabled(true);
mWebView.loadUrl(url);
mWebView.setWebViewClient(new HelloWebViewClient());
}
private void CheckIfServiceIsRunning() {
//If the service is running when the activity starts, we want to automatically bind to it.
if (MyService.isRunning()) {
doBindService();
}
}
private OnClickListener btnStartListener = new OnClickListener() {
public void onClick(View v){
startService(new Intent(MainActivity.this, MyService.class));
}
};
private OnClickListener btnStopListener = new OnClickListener() {
public void onClick(View v){
doUnbindService();
stopService(new Intent(MainActivity.this, MyService.class));
}
};
private OnClickListener btnBindListener = new OnClickListener() {
public void onClick(View v){
doBindService();
}
};
private OnClickListener btnUnbindListener = new OnClickListener() {
public void onClick(View v){
doUnbindService();
}
};
void doBindService() {
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
void doUnbindService() {
if (mIsBound) {
// If we have received the service, and hence registered with it, then now is the time to unregister.
if (mService != null) {
try {
Message msg = Message.obtain(null, MyService.MSG_UNREGISTER_CLIENT);
mService.send(msg);
} catch (RemoteException e) {
// There is nothing special we need to do if the service has crashed.
}
}
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}
private class HelloWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
protected void onDestroy() {
super.onDestroy();
try {
doUnbindService();
} catch (Throwable t) {
Log.e("MainActivity", "Failed to unbind from the service", t);
}
}
#Override
protected void onResume() {
super.onResume();
}
}
From your description it sounds like you are releasing the WakeLock too soon.
If you are just putting that block of code in the onCreate for the Service then you really aren't getting a WakeLock while your streaming code is running. You must have the lock acquired for the duration of the background work.
The pattern I've used for a service like this is:
Create the WakeLock in onCreate (but do not acquire it)
In onDestroy if the WakeLock is held release it. (mostly for safety)
When starting the actual background work, either in onBind or onStartCommand, acquire the lock.
When done with the background work, release the wake lock.
The problem may be specifically with the way a WebView works. That said since this isn't production code, you could try simply 'leaking' the wake lock by removing the release just to see if that helps. Just create and acquire the lock at the start of your activity and not bother with the Service.
The Service isn't really giving you much. The way your code is currently structured you are still going to have problems. Your Activity can be still deleted when in the background even if you have a Service, simply having a service won't stop this. Further because the WebView is a View it really requires an Activity and view hierarchy.

Categories

Resources