requestFeature() must be called before adding the content - android

I want to create an android application to trigger the alarm. I have a button called btnStart. When the user click the button, in 3 second, it should go to AlarmReceiverActivity.java and start play the sound.
the btnStart onclick method look like
btnStart.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int i = 3;
Intent intent = new Intent (MapPage.this, AlarmReceiverActivity.class);
PendingIntent pending =
PendingIntent.getActivity(MapPage.this, 2, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+(i * 1000), pending);
if (toast != null){
toast.cancel();
}
toast = Toast.makeText(getApplicationContext(), "Alarm for activity is set in : "+ i +" second", toast.LENGTH_SHORT);
toast.show();
}
});
and the AlarmReceiverActivity.java look like this
public class AlarmReceiverActivity extends Activity{
private MediaPlayer mMediaPlayer;
private PowerManager.WakeLock mWakeLock;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Wake Log");
mWakeLock.acquire();
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
Button stopAlarm = (Button) findViewById(R.id.stopAlarm);
stopAlarm.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mMediaPlayer.stop();
finish();
}
});
playSound (this, getAlarmUri());
}
to make this short question short, there are some method that I not state above. When I click the button, I got and error. It say that
java.lang.RunTimeException: Unable to start activity ComponentInfo{com.example.splashscreen/com.example.splashscreen.AlarmReceiverActivity}: android.util.AndroidRuntimeException: requestFeature() must be called before adding content
Any idea on how to solve this problem ? Thank you in advance

Chnage the order like this..
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm);

Put this:
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
before this:
setContentView(R.layout.alarm);
From the docs on requestWindowFeature (emphasis added):
Enable extended screen features. This must be called before setContentView(). May be called as many times as desired as long as it is before setContentView(). If not called, no extended features will be available. You can not turn off a feature once it is requested. You canot use other title features with FEATURE_CUSTOM_TITLE.

Related

Launch Activity from FCM

In my application, i need to launch an activity and turn screen on, when high-priority FCM message is received. It's an alarm activity, which is very, very important for users.
On most Android devices, the code is working fine. However, on some Huawei or LG devices, the activity is not launched when the device is in Doze mode, or in the pocket (proximity sensor). The behaviour should be similar like Alarm clocks, calls etc.
Here is my code:
FirebaseMessagingService:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Intent dialogIntent = new Intent(getBaseContext(), AlarmActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
dialogIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
getApplication().startActivity(dialogIntent);
}
Alarm Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set flags so an activity fire on the screen
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
);
setContentView(R.layout.activity_alarm);
.
.
}
I wanted to use SCREEN_BRIGHT_WAKE_LOCK before I launch an activity, but it's deprecated.
I am using in my activity this code:
#Override
protected void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setShowWhenLocked(true);
setTurnScreenOn(true);
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
if (keyguardManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
keyguardManager.requestDismissKeyguard(this, null);
}
} else {
//noinspection deprecation
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
);
}
}
.....
}
To prevent different behavior on different devices I use in my activity layout this:
<android.support.design.widget.CoordinatorLayout
....
android:keepScreenOn="true"
>

Calling button.performClick() automatically just after activity is fully loaded?

I start an activity from a background service which unlocks the phone and starts an activity. What I want to achieve is to go to home screen just after the activity is loaded. I created a button on the activity that I go to just after unlocking and on its OnClick method I used:
moveTaskToBack(true);
Now, I need to call buttonName.performClick() somewhere but where? I tried onResume and onPause so far, but no luck. How or where can I make sure the activity is fully loaded?
//What I do on my Service to start Activity that unlocks the phone
Intent dialogIntent = new Intent(this, StartStopActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(dialogIntent);
This is the activity class:
public class StartStopActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_stop);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
Button returnButton = (Button) findViewById(R.id.button3);
returnButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
moveTaskToBack(true);
}
});
//returnButton.performClick();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
private PowerManager mPowerManager;
private PowerManager.WakeLock mWakeLock;
public void turnOnScreen(){
// turn on screen
Log.v("ProximityActivity", "ON!");
mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "tag");
mWakeLock.acquire();
}
#TargetApi(21) //Suppress lint error for PROXIMITY_SCREEN_OFF_WAKE_LOCK
public void turnOffScreen(){
// turn off screen
Log.v("ProximityActivity", "OFF!");
mWakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "tag");
mWakeLock.acquire();
}
Use startActivityForResult and onActivityResult just turn the screen on and set you parameters to keep the screen on if you want
OnClick method will only be called when you click on a view. You just can't invoke it without clicking on anything.
Just copy the code that you have inside your onclick method and put in inside your oncreate(). or anywhere where you want that piece of code to be executed.
It will not be automatically called if you don't actually click on that view to which you have set the click listener.
Change your code like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_stop);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
moveTaskToBack(true);
}

Turning on screen from receiver/service

I would like my app to be able to turn the screen on and display my app. Let's say I'm setting an alarm and every hour I want my app to be displayed for 2 mins before the device naturally sleeps.
I see that WakeLock (FULL_LOCK) and KeyguardManager are deprecated.
I have created a WakefulBroadcastReceiver and service and these are working.
#Override
protected void onHandleIntent(Intent intent) {
// I need to show the screen here!
for (int i=0; i<5; i++) {
Log.i("SimpleWakefulReceiver", "Running service " + (i + 1)
+ "/5 # " + SystemClock.elapsedRealtime());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
Log.i("SimpleWakefulReceiver", "Completed service # " +
SystemClock.elapsedRealtime());
SimpleWakefulReceiver.completeWakefulIntent(intent);
}
How do I programmatically turn on the screen, get past lock and display my Activity from the IntentService ?
Thanks
You can use this code to turn the screen on.
lock = ((KeyguardManager) getSystemService(Activity.KEYGUARD_SERVICE)).newKeyguardLock(KEYGUARD_SERVICE);
powerManager = ((PowerManager) getSystemService(Context.POWER_SERVICE));
wake = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
lock.disableKeyguard();
wake.acquire();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
You need the following permission in AndroidManifest.xml file:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
EDIT (USE THIS ONE, NOTHING IS DEPRECATED):
There is an one more alternative for doing this, for that you need to launch an activity, In the activity onCreate() you need to add the flags to the window.
For example:
#Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);`
}
I don't know what you're talking about, wakelock is definitely not deprecated. Certain types are no longer the Google preferred way of doing things, but normal wakelocks are still around and still the easiest way of doing this. Make sure to add the ACQUIRE_CAUSES_WAKEUP flag when taking the lock. In fact notice that a WakefulBroadcastReceiver is implemented by using wakelocks.
You can use this code to turn the screen on.
private void turnScreenOn() {
int flags = WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
getWindow().addFlags(flags);
}
You can use this code to keep it on until the wake lock is dimissed.
<uses-permission android:name="android.permission.WAKE_LOCK" />
private PowerManager mPowerManager;
private PowerManager.WakeLock mWakeLock;
#Override
public void onCreate() {
super.onCreate();
mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "Service");
}
private void acquireWakeLock() {
try {
mWakeLock.acquire();
}
catch (Exception e) {
e.printStackTrace();
}
}
private void releaseWakeLock() {
try {
mWakeLock.release();
}
catch (Exception e) {
}
}

Android turn on the screen

I making the application where an activity launch is scheduled by AlarmManager. I would like to appear even if the screen is turned off and device is locked.
To achive this a set the Window flags
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
And try to obtain lock for the screen
if(_lock == null)
{
PowerManager pm = (PowerManager)App.getAppContext()
.getSystemService(Context.POWER_SERVICE);
_lock = pm.newWakeLock(
PowerManager.FULL_WAKE_LOCK, "ScreenOn");
_lock.acquire();
}
The _lock is PowerManager.WakeLock which is released in onPause
protected void onPause()
{
if(_lock != null)
{
_lock.release();
}
}
This code is executed in onCreate and onRestart. Everything works OK if the activity is not launched yet.
But if it was launched earlier the screen is not turned off.
onRestart is called first
onResume is then called
onPause is called immediately
So the activity is not launched. My question is how to turn on the screen in such situation. (I am using API 15).
I came up with the solution. I created a new activity which will be trying to turn on the screen in the onCreate() and then wait until it is turned on. When the screen is ok it will launch the activity which should be displayed. To make the Android always create this activity
public class TurnOnScreen extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (pm.isScreenOn()) openActivity();
else {
registerReceiver(mScreenOnReceiver, new IntentFilter(
Intent.ACTION_SCREEN_ON));
reciever_registered = true;
turnScreenOn();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (reciever_registered) {
unregisterReceiver(mScreenOnReceiver);
reciever_registered = false;
}
}
private boolean reciever_registered = false;
private final BroadcastReceiver mScreenOnReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
openActivity();
}
};
private void openActivity() {
Intent intent = new Intent();
// ....
finish();
}
private void turnScreenOn() {
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
}
}
I am still looking for explanations why the screen is not turned on in onRestart.
Have you heard of "The Lighted Green Room"? Check out the code below, it may be what you're looking for.
http://code.google.com/p/ch-bfh-fbi-mobicomp-2011/source/browse/ch_simplix_android_repetitive_service/src/com/androidbook/longrun/LightedGreenRoom.java?spec=svn38&r=37
Just use your code :
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
in onCreate() only and remove all those other Activity-Cycle methods if they are not doing anything else then this.
I don't think you need any more code to use to perform it.

Launch application from statusbar without re-creation

I am creating application that shows notification icon in statusbar. When user opens statusbar and taps on the icon the application should be launched.
I am searching a way to avoid re-creation of application during this launch. I have created test application and add log messages to handlers onCreate, onRestart, onResume, onStop and onDestroy. Log messages demonstrates the problem:
User starts application - onCreate, onResume
User presses HOME button - onStop
User opens list of applications and starts application again - onRestart, onResume
User presses HOME button - onStop
User opens list of recent applications and selects the application - onRestart, onResume
User presses HOME button - onStop
User opens statusbar and taps on the application icon - onDestroy, onCreate, onResume.
Step 7 has a different behavior then 3) and 5) - there is onDestroy here. In other words, instance of the application is recreated. Is it possible to avoid this recreation?
This is a code of my test activity:
public class MainActivity extends Activity {
private final String LOG_TAG = "com.example.notificationtest";
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showNotification(this);
Log.d(LOG_TAG, "NotificationTest: OnCreate");
}
#Override protected void onRestart() {
super.onRestart();
Log.d(LOG_TAG, "NotificationTest: OnRestart");
}
#Override protected void onResume() {
super.onResume();
Log.d(LOG_TAG, "NotificationTest: OnResume");
}
#Override protected void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "NotificationTest: OnDestroy");
}
#Override protected void onStop() {
super.onStop();
Log.d(LOG_TAG, "NotificationTest: OnStop");
}
private static final int NOTIF_ID = 91371;
public static void showNotification(Context context) {
final Intent result_intent = new Intent(context, MainActivity.class);
result_intent.setAction(Intent.ACTION_MAIN);
result_intent.addCategory(Intent.CATEGORY_LAUNCHER);
//result_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//result_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
//result_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
TaskStackBuilder stack_builder = TaskStackBuilder.create(context);
stack_builder.addParentStack(MainActivity.class);
stack_builder.addNextIntent(result_intent);
PendingIntent pending_intent = stack_builder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
android.support.v4.app.NotificationCompat.Builder builder = new android.support.v4.app.NotificationCompat.Builder(context);
Resources res = context.getResources();
builder.setContentIntent(pending_intent)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.ic_launcher))
.setTicker("test")
.setWhen(System.currentTimeMillis())
.setAutoCancel(false)
.setContentTitle("title")
.setContentInfo("cinfo")
.setContentText("ctext");
Notification n = builder.build();
n.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(NOTIF_ID, n);
}
}
There are some flags, that can be set to result_intent, like FLAG_ACTIVITY_CLEAR_TOP, FLAG_ACTIVITY_CLEAR_TASK and FLAG_ACTIVITY_NEW_TASK. They allow to specify that activity should be restarted on launch (with activity launch mode "singleTop", "singleTask" etc). But what flag should be set to avoid restarting? Probably I should configure pending_intent in some way?
Any help will be very appreciated.
Solved
Thanks a lot for the answers, the problem is solved.
Same problem is described here. I have checked test project from that topic and found difference with my code. To solve the problem my code should be changed in follow way:
final Intent result_intent = new Intent(context, MainActivity.class);
//result_intent.setAction(Intent.ACTION_MAIN); // (1)
//result_intent.addCategory(Intent.CATEGORY_LAUNCHER); // (2)
result_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
another set of flags works too:
result_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
main point was to comment lines (1) and (2)
add this:
result_intent..setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK);
It works like
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
also maintains activity stack

Categories

Resources