I noticed I get the following messages after the screen has been off:
I/Ads﹕ Ad is not visible. Not refreshing ad.
I/Ads﹕ Scheduling ad refresh 60000 milliseconds from now.
I have the following code inside onResume:
if (adView != null) {
adView.resume();
}
I stepped the code and it does get called just fine. It also works just fine if I get out of the activity and back in, the only issue appears to be when coming back after the screen goes off.
Anyone else with this issue?
Thanks.
EDIT: The code I use to create the adview and request
adView = new AdView(this);
adView.setAdSize(AdSize.BANNER);
adView.setAdUnitId(id);
LinearLayout layout = (LinearLayout) findViewById(R.id.main_layout);
layout.addView(adView);
createAdRequest();
The code of createAdRequest():
AdRequest.Builder builder = new AdRequest.Builder();
builder.addKeyword(somekeyword);
AdRequest adRequest = builder.build();
adView.loadAd(adRequest);
I have noticed something else that is odd, I sometimes call createAdRequest again if I notice the keyword has changed, after I make that call the ads seem to stop refreshing as well but this time I don't see any visibility messages, I just don't see anymore requests until I call createAdRequest again.
Did you add code to your onPause and onDestroy as well?
#Override
protected void onPause() {
adView.pause();
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
adView.resume();
}
Ok. I am nothing if not persistent. I tested with this and as a caveat I have been using these flags the whole time. I haven't removed the flags but now with this broadcast receiver it works properly and seems to isolate the issue even more. I will explain.
getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON | // In onCreate
LayoutParams.FLAG_DISMISS_KEYGUARD |
LayoutParams.FLAG_SHOW_WHEN_LOCKED |
LayoutParams.FLAG_TURN_SCREEN_ON);
First of all I already had the receiver for another purpose. And as you can see my flags turn my screen back on but I also have a mechanism that will start the activity for me if needed(Which will need to be tweaked now because of this bug). So the fact that this works as is with all of my other mentioned mechanisms seems to imply a timing issue where AdView checks for the screens status once then doesn't check after it is back on. This was my original suspicion but as you can see the onRecieve method returns void so I can't take responsibility. Not sure if I can completely blame the Author of AdView either since I have seen some weird behavior from this intent before. It might even be a problem with the Activitys' ability to handle the intent too.
Anyway sorry if I am rambling the take away here is that I implemented the receiver to finish the activity when the screen is turned off. And I don't personally worry about starting it back up but if you need to then I added a comment to the code for that too.
[Edit] I will make this a little clearer for the most likely scenario of the Activity context. I was using a Service so that is why mine looked different. I haven't tested this one but it should work the same except I am not sure how you would check if the activity can be finished. Not even sure if that matters. My tested working code will be in my edits though if you need them as a reference.
[Edit] I did end up using this in the Activity context and it worked as expected. If the KeyGuard is not secure. Read comments for full story.
class MyActivity extends Activity {
ScreenReceiver receiver;
#Override
protected void onCreate(Bundle savedInstance){
receiver = new ScreenReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(receiver, filter);
}
#Override
protected void onDestroy(){
unregisterReceiver(receiver);
}
private class ScreenReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i(getClass().getSimpleName(), "Got " + intent.getAction());
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
MyActivity.this.finish();
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// context.startActivity(new Intent(context, MyActivity.class));
}
}
}
}
I had this problem. In my case the size of the banner (adSize) was greater than the available screen area. Make sure you do not have conflicting layouts.
Admob will not refresh unless the ad is visible to user. Obviously when your phone turns off no one can see ads, thus there is no reason for Admob to request another ad.
I personally faced the same problem a couple of times. Once I was placing AdView bellow a ListView. The AdView was not visible until the list was scrolled to the bottom, therefore Admob was constantly logging "Ad is not visible. Not refreshing ad."
Another time, I had no internet connection and the same message was continuously being logged.
I am going to try this approach I think it will pay off. I have been troubleshooting this all day. I should hope that I have a good grasp on it by now. I pasted the relevant part of the post the has the approach. Of course the onResume should be infered. For instance I am going to simply move the ad creation from the onCreate method. If you were using xml to define your ad obviously you would need to change to strictly code.
https://groups.google.com/forum/#!topic/google-admob-ads-sdk/jz-ZQh86lm0
The only way I could have the log stay silent was to remove the entire ad in onPause and add it again in onResume.
If I added the below lines everything works fine, but since this is not the recommended approach then it would be great if the timer was stopped when calling onPause.
admobAdView.pause();
((LinearLayout)admobAdView.getParent()).removeView(admobAdView);
admobAdView.destroy();
admobAdView = null;
Related
I've been a SO member for a while but never actually asked a question, so here goes..
My Aim
I'm trying to make an Android app with two activities. The first is a menu screen (using standard Android UI elements) with a button that opens the gameplay activity. The gameplay activity will have some standard Android UI elements and a FrameLayout containing a Unity 3D scene.
I'm using Unity 5 and Eclipse Luna.
What I've got working
I've made the menu screen with a simple button to start the second activity.
I've followed this tutorial and managed to get my Unity scene embedded in my second activity. All good so far...
The problem
The first time I start the gameplay activity it works fine (I can see the Unity scene embedded in my FrameLayout) but if I close the activity (to return to the menu activity) and then start the gameplay activity again I get this error...
Activity has leaked IntentReceiver com.unity3d.player.UnityPlayer$17#41866de0 that was originally registered here. Are you missing a call to unregisterReceiver()?
What I've tried
I've done a lot of searching online and it looks like I need to call something like this in onPause or onDestroy;
m_UnityPlayer.currentActivity.unregisterReceiver(receiver);
...but I don't know what the receiver is so I can't reference it in my unregisterReceiver call. I've tried creating a BroadcastReceiver, registering it and then unregistering it onPause but it makes no difference.
I found a post on the unity forum that asks the exact same question but, frustratingly, it is unanswered (a lot of questions on the Unity forum seem to be unanswered, that's why I came here with this question).
I've also tried calling this method in onDestroy but it actually quits my whole app when I close the gameplay activity.
m_UnityPlayer.quit();
Code Sample
Here's the code for my gameplay activity (I've removed the imports for clarity);
public class MyEmbeddedUnityActivity extends Activity {
private UnityPlayer m_UnityPlayer;
IntentFilter filter = new IntentFilter("");
private BroadcastReceiver bRec = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//String action = intent.getAction();
Log.d("", "onReceive intent: " + intent);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_embedded_unity);
if(m_UnityPlayer==null){
m_UnityPlayer = new UnityPlayer(this);
int glesMode = m_UnityPlayer.getSettings().getInt("gles_mode", 1);
m_UnityPlayer.init(glesMode, false);
m_UnityPlayer.currentActivity.registerReceiver(bRec, filter);
FrameLayout layout = (FrameLayout) findViewById(R.id.my_frame);
LayoutParams lp = new LayoutParams(200, 300);
layout.addView(m_UnityPlayer, 0, lp);
}
}
public void onWindowFocusChanged(boolean hasFocus){
super.onWindowFocusChanged(hasFocus);
m_UnityPlayer.windowFocusChanged(hasFocus);
}
#Override
public void onDestroy (){
//m_UnityPlayer.quit();
m_UnityPlayer.currentActivity.unregisterReceiver(bRec);
super.onDestroy();
}
#Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
m_UnityPlayer.configurationChanged(newConfig);
}
#Override
protected void onResume() {
super.onResume();
m_UnityPlayer.resume();
}
#Override
protected void onPause() {
super.onPause();
m_UnityPlayer.pause();
}
}
And finally...
The steps I followed to embed the Unity scene were written in 2011. The whole process (of grabbing the files from the Unity project's staging area and copying files around etc.) seems really hacky and undocumented.
Is there a better way of embedding Unity scenes in Android activities with Unity 5? Surely adding a Unity scene to an existing app is a fairly common thing to try to do?
Thanks, any help would be greatly appreciated!
So, I did some more searching and eventually found an answer, right here on SO!
As discussed in this answer, adding this line to the manifest fixes the problem;
android:process=":UnityKillsMe"
so the relevant part of the manifest looks like this;
...
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".Studio"
android:configChanges="orientation|keyboardHidden|screenSize"
android:process=":UnityKillsMe"
android:label="#string/title_activity_home" >
</activity>
...
This forces the gameplay activity to launch in a separate process. This means you can call m_UnityPlayer.quit() in the activity's onDestroy method without the whole app closing.
Simple fix, but annoying that it seems to be completely undocumented.
Hope this helps someone!
I want to make a button that float on homescreen and also work if any other activity is in running.
i have tricked many ideas and also google vary much but i can't get still any solution..
for example i have tried to make my application transparent and full screen and as a system alert flag from this stackoverflow question: Creating a system overlay window (always on top)
#Override
protected void onStop(){
super.onStop();
Intent intent = new Intent(this, ClassNameOfYourActivity.class);
startActivity(intent);
}
and also tried to start my activity at every movement but it is very bad idea like this:
can't get any idea of doing this...Hopefully requested to share me any idea or example if you have experienced about this...
thanzzzz in advance..
The user expects my app to switch off the screen after being used. At the moment, I achieve this with Device Administrator rights and DevicePolicyManager.lockNow(), which works fine if the security settings are set to PIN/Pattern/FaceUnlock, etc.
However, if using Slide/None, the above command just takes the user to the homescreen (or doesn't do anything), which is understandable, since there's nothing to "lock". Is there any way to achieve turning off the screen in such a situation? My app requires SDK>=16, if that matters.
So I guess my question is: How can an app reliably switch off the screen (I'm not holding a wakelock, I'm using the WindowManager-flags FLAG_TURN_SCREEN_ON in onAttachedToWindow()).
The "flow" of my app is:
- Activity is started by an intent while the screen is off, shows above the keyguard/switches on the screen with the above-mentioned flags
- User actively dismisses my Activity, I'm calling lockNow() and finish() and the user expects the screen to turn off. If the user is using the none/slide lock, this doesn't work and instead the user's homescreen is shown
Thanks!
To begin with see here:
To control this policy, the device admin must have a "force-lock" tag
in the "uses-policies" section of its meta-data.
The calling device admin must have requested USES_POLICY_FORCE_LOCK to
be able to call this method; if it has not, a security exception will
be thrown.
Depending from the code you got, here's a pretty nice explanation of what can be wrong in your case (of course any code provided here will be of use!).
I've heard on several occasions, that calling twice the code DevicePolicyManager.lockNow() will do the trick and here's one way of doing that:
mDPM = (DevicePolicyManager)getApplicationContext().getSystemService("device_policy");
Handler handlerUI = new Handler();
handlerUI.postDelayed(new Runnable() {
#Override
public void run() {
mDPM.lockNow();
}
}, 200);
finish();
mDPM.lockNow();
Here I found a more elaborate version of the same thing:
Android DevicePolicyManager lockNow() problem
public class SMSMessagingActivity extends Activity {
/** Called when the activity is first created. */
public static DevicePolicyManager mDPM;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
}
public static void LockNow(){
mDPM.lockNow();
}
}
ComponentName devAdminReceiver; // this would have been declared in your class body
// then in your onCreate
mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
devAdminReceiver = new ComponentName(context, deviceAdminReceiver.class);
//then in your onResume
boolean admin = mDPM.isAdminActive(devAdminReceiver);
if (admin)
mDPM.lockNow();
else Log.i(tag,"Not an admin");
Let's hope that the last workaround will work correctly.
Cheers
I used Delyan's comment to achieve this:
If you request WRITE_SETTINGS, you can probably set the screen timeout to be 1 sec - android.provider.Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, 1000); Of course, then you're messing up the user's settings but I can't figure out a better way to do it. I have seen apps that do it - NoLED is the most prominent example.
I'm new to Android development. I am trying to monetize a live wallpaper that I built and the ad delivery company wants me to call their code from the onCreate of an activity.
The live wallpaper didn't have an activity before I started to monetize it, being an extension to WallpaperService, so I've added one. I've managed to create the activity and make it translucent, but it doesn't close when the dialog closes. I cannot edit the dialog code since it is being created by a call into a .jar, so I thought I could setup a listener for when the dialog is dismissed, but I wasn't able to find any practical examples that might help with the code below.
LWP.java
public class SBLiveWallpaper extends WallpaperService {
super.onCreate();
Intent i = new Intent();
// i.setClass(this, MainActivity.class);
i.setComponent(new ComponentName("appname", "appname.MainActivity"));
// i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
activity_main.xml has no elements (just the RelativeLayout)
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppBucksAPI.initialize(this, APPID, "APIKEY", true, null, null);
AppBucksAPI.userOptOutDialog(this, "marketname");
}
I could make the activity be non-transparent, and just add a close button, but that is ugly and confuses users.
Edit for clarification: I had tried originally to call the dialog directly from the service's onCreate(). It causes the LWP to crash in the screen where you can make it the active LWP. The error I get is android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application.
I contacted AppBucks support before making the original post here. Their response (pasted below) prompted me to create the translucent activity.:
I believe this error means that there is a problem with the first parameter you are passing to the AppBucksAPI.userOptOutDialog method… the call which looks like this from the docs:
AppBucksAPI.userOptOutDialog(this, "<App Name>");
This call expects an Activity or Activity context as the first parameter. It needs this because our default opt out dialog uses an AlertDialog call, which requires an active Activity for it to display correctly. If you are already creating an Activity along with your service, you should pass that activity as the first parameter instead of “this” (or you could move this call to the onCreate of that activity instead of onCreate for the service).
If you don’t have an Activity in your app, I found this StackOverflow question which has an answer that may help (in a nutshell, you can create a transparent activity when your service starts up, and make the userOptOutDialog call from that instead of your service’s onCreate method):
Display AlertDialog as system overlay window from Service
Unfortunately, the above article covers creating the activity and closing the dialog under the assumption that the person reading it has access to the dialog's code. Since I do not have access to that, because it is imported into my project as a library, I need to know how to listen, from the parent activity, for the child to finish.
I did some digging and it looks like either of these could work, depending on how the activity is started from the dialog call my code makes:
http://developer.android.com/reference/android/app/Activity.html#finishActivityFromChild(android.app.Activity, int)
or
http://developer.android.com/reference/android/app/Activity.html#finishFromChild(android.app.Activity)
I'll give those a try tonight.
The AppBucks SDK also exposes the following functions:
setIconAdsEnabledForUser
setPushAdsEnabledForUser
The AppBucksAPI.userOptOutDialog is basically a convenience function that wraps calls to these in an AlertDialog. For your app, it probably makes more sense to forego the convenience function and write your own AlertDialog that calls the enable functions directly. That way you will have full control over what happens when the dialog is dismissed and can close the new activity you created when you need to.
Looking at the AppBucks API and documentation, I don't think using an Activity is mandatory. It is just the most common way.
I think you can call AppBucks method in your service onCreate as well?
When dismissing your dialog, send an intent to your activity for it to close itself.
For instance
Put this in the dialog dismiss method:
sendBroadcast(new Intent(MainActivity.ACTION_TERMINATE));
Then in the MainActivity add and register a BroadcastReceiver:
Add fields for the receiver and the filter in the activity:
private ActivityBroadcastReceiver mReceiver;
static final IntentFilter mFilter = new IntentFilter();
static {mFilter.addAction(ACTION_TERMINATE);}
Instantiate it in onCreate():
mReceiver = new ActivityBroadcastReceiver();
Register it in onResume():
registerReceiver(mReceiver, mFilter);
Unregister it in onPause():
unregisterReceiver(mReceiver);
And the broadcast receiver's inner class in the activity would look like this
private class ActivityBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
String action = intent.getAction();
if (ACTION_TERMINATE.equals(action)) {
finish();
}
} catch (Exception e) {
Log.w(mTag, "Oops: " + e, e);
}
}
}
I'm making a SIP application, and I've got pretty much everything working that i want to except one thing. I cant get the activity to launch when a SIP call occurs.
I'm working with a SIP library that starts a 'phone' service which deals with the handling of incoming calls etc, and when i create an instance of the 'phone' I then register listeners which detail what i want to happen. So to handle incoming calls i register an 'OnIncommingCall' listener.
If the app isn't currently open at the time i want it to launch the app. so my listener is:
thisPhone.setIncomingCallListener(new OnIncomingCallListener()
{
public void OnIncomingCall(String remoteContact, int accountId)
{
if(MainActivity.this.getIsOpen())
{
MainActivity.this.setIsCallIncomming(true);
MainActivity.this.setCurrentCaller(remoteContact);
MainActivity.this.setMainUIEles();
}
else
{
Intent i = new Intent(getApplicationContext(), MainActivity.class);
i.putExtra("isCallIncomming", true);
i.putExtra("currentCaller", remoteContact);
i.putExtra("isRegistered", true);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}
}); //incoming call listener
However when the call comes, it rings but the app wont open, but if i open the app from the launcher whilst the call is still ringing then it will open and know the call is there.
Is the problem because I'm trying to start the Activity which defined the listener?
I've tried all sorts of flags and combinations (SINGLE_TOP etc) can i can't get it to work.
Any help would be appreciated!
DJOodlen
Well this was a silly mistake on my part.
After putting in some toasts so I could see where in the code each bit was going I realised that getIsOpen() never returned false. That's because it wasn't being called on the onPause() method as wells as the onDestroy() method...
Ooops!