I am trying to implement the fairly new Android TagManager from Google. I can't seem to be able to load the default values.
I have created my default json file:
assets/tagmanager/GTM-xxx.json
Which looks like this:
{ 'eulaTextVersion': '1' }
I have also added this code to actually pull the default file if nothing is found on the server:
TagManager mTagManager = TagManager.getInstance(this);
// The container is returned to containerFuture when available.
ContainerOpener.openContainer(
mTagManager, // TagManager instance.
CONTAINER_ID, // Tag Manager Container ID.
OpenType.PREFER_NON_DEFAULT, // Prefer not to get the default container, but stale is OK.
null, // Time to wait for saved container to load (ms). Default is 2000ms.
new ContainerOpener.Notifier() { // Called when container loads.
#Override
public void containerAvailable(Container container) {
// Handle assignment in callback to avoid blocking main thread.
mContainer = container;
}
}
);
int eulaTextVersion = (int) mContainer.getDouble("eulaTextVersion");
However, when I debug, my int eulaTextVersion is always zero, I can never get it to 1 like it should be from my default json. Could someone please help me out and show me where I am going wrong?
Thank you for the help.
Probably Google Tag Manager already downloaded first version for you. First version is probably empty. Just make next version with "Values" that contain "eulaTextVersion" and "Publish" it.
If you do not know how to set those values on your Google Tag Manger account look at: http://youtu.be/Xe8W5w68BRg?t=8m26s
You shouldn't be using quotation for numerical values. Try the following instead
{ 'eulaTextVersion': 1 }
Related
I've been trying to print with Brother Print SDK 3.5.1 on Android 8.1.0. I keep getting ERROR_WRONG_LABEL.
This is the code I use
void printPdf() {
// Specify printer
final Printer printer = new Printer();
PrinterInfo settings = printer.getPrinterInfo();
settings.printerModel = PrinterInfo.Model.QL_810W;
settings.port = PrinterInfo.Port.NET;
settings.ipAddress = "192.168.1.73";
settings.workPath = "storage/emulated/0/Download/";
// Print Settings
settings.labelNameIndex = LabelInfo.QL700.W62RB.ordinal();
settings.printMode = PrinterInfo.PrintMode.FIT_TO_PAGE;
settings.orientation = PrinterInfo.Orientation.PORTRAIT;
settings.isAutoCut = true;
printer.setPrinterInfo(settings);
// Connect, then print
new Thread(new Runnable() {
#Override
public void run() {
if (printer.startCommunication()) {
PrinterStatus result = printer.printPdfFile("/storage/emulated/0/Download/hello world red.pdf", 1);
if (result.errorCode != PrinterInfo.ErrorCode.ERROR_NONE) {
Log.d("TAG", "ERROR - " + result.errorCode);
}
printer.endCommunication();
}
}
}).start();
}
My printer model is QL-810W and I use the black and red W62 roll.
I've tried the Sample Application, where setting W62RB in labelNameIndex prints fine.
Changing the roll for different one with different width didn't help.
I've also tried iterating over numbers 0 to 50 and using them as labelNameIndex.
Based on this thread, I thought that the issue may be in specifying the workPath attribute. Setting workPath to getContext().getCacheDir().getPath() results in ERROR_OUT_OF_MEMORY instead of ERROR_WRONG_LABEL. Not specifying workPath and adding <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> to AndroidManifest.xml results in ERROR_WRONG_LABEL
EDIT
I've modified the Brother Sample app and uploaded it to GitHub. The app now launches Activity_PrintPdf.java by default where I inserted my printing code with hardcoded values at the beginning of onCreate method - this works fine and prints the PDF file as expected.
Then I created a new Empty Activity project in Android Studio, copy pasted the library, added the imports to build.gradle and copy pasted the permissions into AndroidManifest.xml. Then I copy pasted the printing code at the beginning of onCreate method in MainActivity.java. Running the app results in ERROR_WRONG_LABEL.
This is the modified working example app and this is the one that results in the error. I want to use the code as native module that I call from my React Native app, so it's important that I manage to set up the printing code from scratch rather than modifying the existing example app.
EDIT 2
I've inspected the library with a debugger: when executing printer.setPrinterInfo(mPrinterInfo) the library internally calls private boolean createWorkPath(String dirPath) of Printer object. On return from this method, the debugger shows Source code doesn't match the bytecode and seems to forget the created directory. This also internally sets mResult.errorCode = ErrorCode.ERROR_WORKPATH_NOT_SET. However, instead of rising any error here the code just silently proceeds, which later results in ERROR_WRONG_LABEL when trying to print. Running the same code snipper in the modified Sample app works fine.
I'd be grateful if you could help or suggest what to try next.
Thank you!
I've now fixed the issue, which was that the Brother library silently failed to create a temporarily folder and instead of reporting an error, it continued and failed later to read the label information. Based on this thread, it is now required to specify runtime file read and write permissions as opposed to the compile-time ones in AndroidManifest.xml.
Adding
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
at the beginning of onCreate before the printing code fixed the issue.
I'm trying to add a BackdoorMethod to a Xamarin.Forms application to bypass the login (IDP - opened in chrome browser) step. I have the feeling that the method is not getting triggered, but not sure, and I don't know how could I make sure about it.
I've read the documentation here: https://learn.microsoft.com/en-us/appcenter/test-cloud/uitest/working-with-backdoors
Check this thread: https://forums.xamarin.com/discussion/85821/xamarin-uitest-backdoor-on-droid-with-splash-screen-how-do-i-access-my-mainactivity
Checked this example: https://github.com/brminnick/UITestSampleApp/tree/master/Src
In the MainActivity.cs file I've defined the BackdoorMethod:
[Preserve, Export(nameof(BypassLoginScreen))]
public string BypassLoginScreen()
{
// some additional code here. the code is working, when I called it
// directly from OnCreate it was executed without any error
return "called";
}
From the test case i'm trying to invoke it like:
public constructorMethod(Platform platform)
{
this.platform = platform;
app = AppInitializer.StartApp(platform);
var result = app.Invoke("BypassLoginScreen"); // result == "<VOID>"
}
I'm not getting any error message, the method simply not called, or not returns anything. (or i don't know what's happening there with it, because breakpoint also not working as the app started from the device)
This should be already working. I have similar code and it works for me.
you can add inside your function
Android.Util.Log.WriteLine(Android.Util.LogPriority.Info, "BypassLoginScreen", $"Some text as info");
And observe the result in Device Logs, Filter by BypassLoginScreen to see if there is any log created with the tag BypassLoginScreen
In my app, I have the following code that tells me if a feature is enabled by default :
public boolean getFeatureEnabled()
{
return mPrefs.getBoolean("FEATURE_ENABLED", DEFAULT_ENABLED);
}
This preference is overwritten only when the user changes the setting from UI. So by default it draws its value from DEFAULT_ENABLED which is a class variable somewhere.
In the current version, DEFAULT_ENABLED is true but on the next version of my app will be false.
The problem is that after the update, with the above code the old users who did not change the default setting from UI will have their feature disable - and I want to avoid this.
Any advices on how to handle this ?
As I understand, you have a feature that was enabled by default but this default was never written to SharedPreferences unless explicitly changed by the user.
Now you want the feature to be disabled by default but without affecting the behavior for users that already have it enabled.
I can think of 3 options:
Option 1 If you are already saving the last version, you could check that in your migration logic:
private void migratePreferences(Context context) {
SharedPreferences prefs = context.getSharedPreferences("your_preference_file", MODE_PRIVATE);
int lastKnownVersionCode = (prefs.getInt("LAST_INSTALLED_VERSION", BuildConfig.VERSION_CODE);
prefs.edit().putInt("LAST_INSTALLED_VERSION", BuildConfig.VERSION_CODE).apply();
//this is the old featureEnabled check
boolean oldPreferenceValue = prefs.getBoolean("FEATURE_ENABLED", true);
boolean newPreferenceValue;
if (prefs.contains("FEATURE_ENABLED")) {
//the feature was modified by the user so respect their preference
newPreferenceValue = prefs.getBoolean("FEATURE_ENABLED", false);
} else if (lastKnownVersionCode == BUGGY_VERSION_WITH_FEATURE_ENABLED_BY_DEFAULT) {
//the user is updating from the buggy version.
// this check could include a range of versions if you've released several buggy versions.
// this is also where option 2 would be inserted
newPreferenceValue = oldPreferenceValue;
} else {
//the new default that will apply to fresh installs
newPreferenceValue = false;
}
//save the preference
prefs.edit().putBoolean("FEATURE_ENABLED", newPreferenceValue).apply();
}
This, however depends on your already having a call to this method somewhere in your app startup code.
Option 2 In case you don't, there is still hope. You can check if this is your first install using the answers given in this StackOverflow answer
Option 3 You can release an intermediate version of your app that behaves as it does now but saves the unsaved default setting in SharedPreferences. This will keep the feature AS IS for your eager users but you will have to wait until a significant portion of users updates before releasing the desired behavior.
Put another flag "FIRST_TIME" as "true" in your preferences in new build. Check on the very first screen of your app
if(FIRST_TIME==true)
{
//put FEATURE_ENABLED = false;
//put FIRST_TIME = false;
}
By doing this FEATURE_ENABLED will set to false for the first time the user launches the app and will not consider the default value
I'm attempting to draw an icon for an achievement using Google Play Game Services API.
However, it is silently failing.
Approach/Issue:
The URI for the image is retrieved successfully, exists and is valid.
I use ImageManager.loadImage to get the image, with an OnImageLoadedListener for callback (com.google.android.gms.common.images.ImageManager).
However OnImageLoadedListener's method, onImageLoaded, is never called.
No error's, no evidence, just completely ignored, I even waited 10 minutes just in case.
Code:
// Get URI [is valid, exists, is of type png, I checked]
Uri uri = getAchievementIconUri(id);
// Use ImageManager to get the icon image
ImageManager.create(context).
loadImage(new ImageManager.OnImageLoadedListener() {
#Override
public void onImageLoaded(Uri u, Drawable d, boolean r) {
/*
* This code is never reached, no call to onImageLoaded is made!
*/
}
}, uri);
It's probably a very late answer, but it might help other people experiencing the same. From the latest google documentation, https://developers.google.com/android/reference/com/google/android/gms/common/images/ImageManager.html#public-methods
Note that you should hold a reference to the listener provided until the callback is complete. For this reason, the use of anonymous implementations is discouraged.
This might explain the behaviour you experienced, as in the first code snippet provided, no reference to the Listener was retained.
Well, for what it matters, I never solved the problem entirely.
It seems that it actually displays the icons occasionally, whenever it feels like it.
I implemented a workaround that loads a compressed, cached version of the image and later replaces it with the ImageManager provided image if it can be bothered doing so.
If anybody works out the correct answer then I will remove this workaround, but until then its here for anybody with the same issue.
Code that loads the local icons:
public Bitmap loadDefaultAchievementIcon(final String id) {
// Get drawable ID for achievement
// iconIdMap is a map of achievement ID strings against their drawable res IDs
int resID = iconIdMap.containsKey(id) ? iconIdMap.get(id) :
// Fallback/unknown icon
R.drawable.ic_action_achievements;
// Load and return bitmap
InputStream is = getResources().openRawResource(resID);
Bitmap bitmap = BitmapFactory.decodeStream(is);
return bitmap;
}
My requirement is, First time application is installed in the Android phone, Need to get the licence code from particular shop/organization. I have created generation key using phone model number.nOW THE PROBLEM IS If its first only need to show license screen otherwise go to first screen. How we can identify the particular app is installed already or not . / from the registry ? In here registry is available.
I couldn't explore my very deeply or clearly. Sorry for that.
Please help me.
Thanks in advance...
You could always set a bool value in the android.content.SharedPreferences, then in the first oncreate() check to see whether that bool value is false.
If it is push the license screen intent and perform a check for application, if its there update the preference to true. So on next start it will skip over it, where you can load your main screen.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
settings = getSharedPreferences(PREFS_NAME, 0);
boolean enteredDetails = settings.getBoolean("FirstTime", false);
if(enteredDetails){
setContentView(R.layout.main); //loads the main screen
}
else{
startActivityForResult(new Intent(this, License.class), GET_DETAILS);
}
}
You can simply use Context.openFileInput() / Context.openFileOutput() to store a piece of information that will tell your app whether the license screen was already shown. This way you can use something like this in your main Activity's onCreate():
if (nothingWrittenInAFileCalled(FILE_NAME)) { // using Context.openFileInput()
showLicense();
writeAFileCalled(FILE_NAME); // using Context.openFileOutput()
}
If this is not satisfactory, this is also something you can check on license server side. If you send the license server a hash of the IMEI, as an example, your license server will be able to determine whether the app was already installed or not. In that case, prefer a non reversible hash: this is to avoid sending/storing the IMEI as one can see this piece of information as private data.