I released my Android app two days ago, using admob advertising. I used my personal phone as the test phone, but took out the test mode code before releasing it. My admob status is active and I get requests and impressions on the report, but whenever I try to use the app on my personal phone i only get "test ads". I don't know why. I looked through the code of my app and can't find anything amiss. And i did delete the test version of the app and then download the released version from the market.
I'm not sure why the test ads are appearing in your app, but one way to shut them off is to go to your Admob App Settings, and choose the option "Disable test mode for all requests" as your Test Mode setting.
You customers would not have been seeing the debug ads. You probably have a line like:
AdManager.setTestDevices( new String[] {
AdManager.TEST_EMULATOR, // Android emulator
"E83D20734F72FB3108F104ABC0FFC738", // My T-Mobile G1 Test Phone
}
Assuming E83D20734F72FB3108F104ABC0FFC738 is you're personal phone, any time that phone makes a request it will get a test ad. All other phones will not be eligible for test ads, unless they are also individually added to that method.
Nick's answer works. (But is missing the final parenthesis.)
But what if I want to give my (not yet released) Android app out to 10 friends?
Is there any java code that says "treat ALL phones as test devices"?
Here is code for treat all devices as test devices:
String aid = Settings.Secure.getString(context.getContentResolver(), "android_id");
try {
Object obj;
((MessageDigest) (obj = MessageDigest.getInstance("MD5"))).update(aid.getBytes(), 0, aid.length());
aid = String.format("%032X", new Object[] { new BigInteger(1, ((MessageDigest) obj).digest()) });
} catch (NoSuchAlgorithmException localNoSuchAlgorithmException) {
aid = aid.substring(0, 32);
}
adRequest.addTestDevice(aid);
Related
I have integrated the play core in-app update it's working fine in the testing track but when a release is published in the production track it's always giving the UPDATE_NOT_AVAILABLE flag. I think the problem might be because Timed Publishing/Publishing Overview is enabled. Is there any fix or any setting which I have to change from the play console itself? or do I have to implement something in my android end?
here is the Implemented code-
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(context);
Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
appUpdateInfoTask.addOnCompleteListener(listener -> {
if (listener.isSuccessful()) {
Log.d(TAG, "Update Available " + (listener.getResult().updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE)); // returns false
Log.d(TAG, "Update Allowed" + listener.getResult().isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)); // returns false
Log.d(TAG, "Update Availibility" + listener.getResult().updateAvailability()); // returns 1 that is UPDATE_NOT_AVAILABLE
if (listener.getResult().updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& listener.getResult().isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
try {
appUpdateManager.startUpdateFlowForResult(
listener.getResult(),
AppUpdateType.IMMEDIATE,
activity,
1001);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "showPopup: ", e);
dialog.show();
}
} else {
Log.d(TAG, "no update: " + listener.getResult());
dialog.show();
}
} else {
Log.e(TAG, "no update: ", listener.getException());
}
});
I had a similar problem yesterday, and in my desperation put what should of been a comment about having a similar problem as an answer... #Natty showed me the error of my ways, and I felt bad, so made sure I'd come back with a better actual answer:
I discovered that the likely culprit is google play app signing. It looks like they changed things in August 2021 so as the default is to allow google to manage the app signing, which means your app is signed by a different key with each release, and thus your releases have different signatures, and it won't find the updates. The exceptions is internal app sharing.
Sadly, there appears to be no way to opt-out
You can't disable App Signing after being activated as you can read in the image below:
see this post
It get worse... because ya know google... your can't delete you app either, the only thing you can do is to
unpublish the app.
Then create a new version on the google play store. Change the applicationId to some slight variant so it counts as a different app.
When adding you first release for the new app in any track, make sure to select the appropriate option for app signing above where you drop in the app bundle
click use different key
Either use a keystore generated from android studio or make a new one. From then on google will use that same keystore for signing all future releases of the app.
I even went back and double checked this was the case for me, by checking the older version of the app and the new version on internal testing tracks. Indeed, the new version using the same app signing keystore works for in-app updates, but the older version with google app signing did not.
Just bear in mind a whole new app has to go through the review process, which can take 1-3 days for new apps (seemed to be much quicker once the initial review is done)
Can Always-on VPN switch be on programmatically?
I have added the device admin permission. After that i have set always on in with device admin
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mDeviceAdminSample = new ComponentName(this, DeviceAdminReceiver.class);
isAdminApp = mDPM.isAdminActive(mDeviceAdminSample);
if (isAdminApp) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mDPM.setAlwaysOnVpnPackage(mDeviceAdminSample,"", true);
}
} catch (PackageManager.NameNotFoundException namenotfoundexception) {
namenotfoundexception.printStackTrace();
} catch (Exception ex) {
}
}
but it's not enabling the always on.
i have added package name insted of
mDPM.setAlwaysOnVpnPackage(mDeviceAdminSample,"my.app.package.name", true);
but still not enabling the switch.
Then what this code is doing?
How can i enable it programatically?
I want this to be like below image
According to docs, setAlwaysOnVpnPackage can only be used by the profile owner (usually the MDM client on work profile) or device owner (for fully managed devices):
Called by a device or profile owner to configure an always-on VPN connection through a specific application for the current user. This connection is automatically granted and persisted after a reboot.
As a personal profile user - I don't want my VPN to decide for itself when to connect (set always on programmatically will immediately connect the VPN, if implemented correctly).
As a work profile user (wearing the hat of an employee), it's not my decision, but my organization's (via the profile owner app).
So, all in all, this behavior makes sense.
Update:
Instead implementing MDM, which could take a lot of work, you can clone, build and debug Google's Test DPC app, which have everything you need to test toggling always-on VPN programmatically.
It also have million other things, which you don't need so be sure to ignore the rest :)
I haven't looked at their code, but I suggest searching for usages of setAlwaysOnVpnPackage function.
Google's Test DPC app:
Link to Play Store
Link to GitHub repo (to build & debug it yourself)
I want you to know I'm a newbie to Android Development.
I have developed an Android application. Before releasing the app I tested it many times on my device and several others to check if it crashes or not. The app passed all the tests.
Now the app is crashing on some of the user's device and how to know reason of crashing app of the user's device.
I'm a bit confused about how to tackle problems like this.
private static void logInitError(#NonNull String message) {
CrashLog.log(message);
CrashLog.log(locationManager == null ? "!!! NOT INITIALISED !!!" : "locationManager initialised");
DebugTestException debugException = new DebugTestException();
CrashLog.logException(debugException);
}
private static void logInitErrorNoProvider(#NonNull String message) {
CrashLog.log(message);
CrashLog.log(locationManager == null ? "!!! NOT INITIALISED !!!" : "locationManager initialised");
DebugTestException debugException = new DebugTestException();
CrashLog.logException(debugException);
}
The best way to monitor the app is to use firebase crashlytics.
You will get real-time analytics from your app, refer the official guide for implementation.
I'm failing in implementing Push Notification in Codename One, Android.
It seems registering push works perfectly now as follow, because public void registeredForPush(String deviceId) method of PushCallback interface is called successfully.
Display.getInstance().callSerially(() -> Display.getInstance().registerPush());
But, it seems server doesn't work.
new Push(PUSH_TOKEN, "Hello World", deviceId)
.gcmAuth(GCM_SERVER_API_KEY)
.send();
Above, deviceId is from the Android Phone itself, that is, app works as Push notification server as well as client.
I think this code should push notification to the phone itself.
Of course, I followed the guide here.
I also turned on Notification of this app in Phone settings and my codename one account plan is pro, but I don't know why notification arrived to my Android Phone.
Please help me with this issue.
(NetBeans IDE 8.2 (Build 201705191307)
Codename One Version: 3.7.1)
I found what the reason is.
First of all, I had to use Push.getPushKey() method to get phone's device id`.
But I had managed phones device ID as follows:
public void registeredForPush(String deviceId) {
store(deviceId); //this should be store(Push.getPushKey()); instead.
}
But it was absolutely wrong.
As Shai said in comment, the device id for pushing notification should be start 'cn1-gcm', but here deviceId was not so.
I'm just confused why registeredForPush() method has devieId as its parameter, which makes developers confusing.
Anyway, it works perfectly now while I'm using Push.getPushKey() in my code.
I'm very happy now and thanks to Shai and all of Codename One.
The context:
I use AdMob mediation to display banner ads in my app.
I integrated Millennial ad network SDK and Millennial AdMob adapter.
Problem: my app supports Android API 9+, whereas Millennial SDK supports API 16+. Worse, instead of gracefully failing (returning no ad to the AdMob mediation layer so that it can continue going down the mediation waterfall), the SDK crashes on devices running Android < 16 (Fatal Exception: java.lang.NoSuchMethodError
android.webkit.WebSettings.setAllowUniversalAccessFromFileURLs)
Apparently Millennial developers are not planning to fix this, they recommend publishing 2 distinct APKs ("<16" without their SDK and "16+" with their SDK), which is a troublesome solution.
I would prefer a simpler solution: on devices running Android API < 16, I'd like to reproduce what happens when an AdMob adapter is missing: AdMob mediation just goes to the next network.
This would mean unloading or erasing the Millennial adapter class before I instantiate the AdMod mediation banner.
The question:
Is there any way to prevent any future instantation of a given class (from a 3rd party library) at runtime? (e.g. by forcing a ClassNotFound exception)
Use two ad units. You can set up two banner ad units at AdMob.com, one with MillennialMedia in the mediation stack and one without. You can then check the API level of the device at runtime as Bonatti suggests, and set the ad unit ID on your AdView as appropriate prior to requesting ads.
If MillennialMedia is not in the mediation configuration for the ad unit being used, their adapter will not be instantiated by the Google Mobile Ads SDK.
I am exactly in the same situation as you.
After doing a lot of research and black magic with class loaders, etc., I've found a dirty but working solution:
// At onCreate() or wherever it makes sense
if (Build.VERSION.SDK_INT < 16) {
// Must be done before requesting the first ad
disableMMediaAdapter();
}
m_adView.loadAd(adRequest);
// ...
private void disableMMediaAdapter()
{
try {
Field fInitialized = MMSDK.class.getField("initialized");
fInitialized.setAccessible(true);
fInitialized.set(null, true);
} catch (Exception e) {
e.printStackTrace();
}
}
By tricking the SDK into believing it's initialized it will fail miserabily when an ad is requested through it and the next mediation adapter will be called.
This will work as long as they don't change their class desing too much.
Is there any way to prevent any future instantation of a given class at runtime? (e.g. by forcing a ClassNotFound exception)
You can, before loading the Adapter, check the OS version, and if its below your threshold
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.THE_VERSION_I_WANT_MINIMUM) {
// doStuffs()
} else {
throw new MyException("Stuffs have stuffened...");
}