Delete Persistent Store data when App is uninstalled/deleted - blackberry

I have a BlackBerry application that starts (App load) with a Registration screen when the App is first installed. Later, the App will load with the home screen. Registration screen only appears on first load. I am achieving this by storing a boolean value in PersistentStore. If the value exists, then Registration screen will not appear.
PersistentStoreHelper.persistentHashtable.put("flagged",Boolean.TRUE);
PersistentStoreHelper.persistentObject.commit();
UiApplication.getUiApplication().pushScreen(new MyScreen());
I am aware of the fact that in order to delete the Persistent Store on deleting/uninstalling the App, I have to make the Hashtable a subclass of my own and therefore I have declared the Hashtable in a separate class:
public class PersistentStoreHelper extends Hashtable implements Persistable{
public static PersistentObject persistentObject;
public static final long KEY = 0x9df9f961bc6d6daL;
public static Hashtable persistentHashtable;
}
However this has not helped and the boolean value of flag is not cleared from PersistentStore. Please advice.
EDIT: When I change the above PersistentStoreHelper class to
public static PersistentObject persistentObject =
PersistentStore.getPersistentObject(KEY);
and remove
PersistentStoreHelper.persistentObject =
PersistentStore.getPersistentObject(PersistentStoreHelper.KEY);
from class B where boolean value is being saved, I observe that the boolean value is removed every time the App is closed. This should not happen and the value should only be removed in case the App is deleted/uninstalled. Any pointers?

The way this works is that the BlackBerry OS looks at the objects you are storing in the PersistentStore. If it recognizes that those objects can only be used by your app, then it will delete them when you uninstall the app. However, if the classes of the stored objects are classes that are used by other apps, then your data will not be deleted.
You have declared your helper class like this:
public class PersistentStoreHelper extends Hashtable implements Persistable{
but the helper class is not what is being stored. Your helper class is just a helper, that stores other things for you. In your case, it is storing this:
public static Hashtable persistentHashtable;
but, that object is of type java.util.Hashtable, which is a class used by many apps. So, it won't be deleted when you uninstall your app. What you should do is something like this:
public class PersistentStoreHelper implements Persistable { // so inner class = Persistable
public static PersistentObject persistentObject;
public static final long KEY = 0x9df9f961bc6d6daL;
/**
* persistentHashtable is now an instance of a class that
* only exists in your app
*/
public static MyAppsHashtable persistentHashtable;
private class MyAppsHashtable extends Hashtable implements Persistable {
// don't need anything else ... the declaration does it all!
}
}
I can't see it here, but I'm assuming that somewhere you have this code:
persistentObject = PersistentStore.getPersistentObject(KEY);
and then when you want to save the data back to the store, you're doing something like this;
persistentHashtable.put("SomeKey", someNewData);
persistentObject.setContents(persistentHashtable);
persistentObject.commit();
just adding data to the persistentHashtable doesn't save it (permanently). Hopefully, you already had that part somewhere.
Note: if you make these changes, don't expect this line of code to work, the next time you run your app:
persistentHashtable = (MyAppsHashtable)persistentObject.getContents();
because the last version of your code did not use the MyAppsHashtable class, so the loaded data won't be of that type. This is one reason that it's important to get this right the first time. In general, I always wind up saving data in the PersistentStore that's contained in one top level Hashtable subclass, that implements Persistable. I may later change what goes in it, but I won't ever change the signature of that top-level storage object. Hopefully, you haven't released your app already.
Update: In response to your comment/question below:
if (PersistentStoreHelper.persistentObject.getContents() == null) {
PersistentStoreHelper.persistentHashtable = new MyAppsHashtable();
PersistentStoreHelper.persistentObject.setContents(PersistentStoreHelper.persist‌entHashtable);
} else {
PersistentStoreHelper.persistentHashtable =
(MyAppsHashtable)PersistentStoreHelper.persistentObject.getContents();
}

Related

How to use scoped_model with Shared Preferences?

I am add state management to my chat app using scoped_model.
My question is how use scoped_model with shared preferences. So on app startup Model state is fill with values from shared preferences. For example stored username will be retrieve from shared preferences and then store in UserModel username state.
I have look but no find tutorial how to do.
I have find this sample from FlutterCinematic main.dart:
void main() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
runApp(ScopedModel<AppModel>(
model: AppModel(sharedPreferences), child: CinematicApp()));
}
Is this best way to do?
What is best way?
Thanks!
I know it's been a while since this question was asked. But I am still gonna' answer it anyway.
I had the same problem when I was developing an android app using shared preferences and scoped model. My idea was to initialize the values in scopedmodel when the app starts. And the way I did it was to call the function within the constructor of the model.
Let's say my scoped model is:
class AppModel extends Model {
String variable1;
String variable2;
int variable3;
//Getter functions go here
//Setter function (though not a pure setter but a function that sets the values)
void setValues() {
SharedPreferences.getInstance().then(
(prefs) {
variable1 = prefs.getString('var1');
variable2 = prefs.getString('var2');
variable3 = prefs.getInt('var3');
));
}
AppModel(
setValues();
);
}
Now when you initialize the model before the Material app, its values will get initialized.

MVC 5 Identity 2 - customer UserStore methods not being called

I am trying to implement a custom UserStore for my MVC 5 application so that I can delegate the database commands to my existing database project.
The tables in my database use integer keys, so I created a custom UserManager that inherits UserManager<User, int> instead of just UserManager<User>. For that reason, I also created a custom UserStore that implements IUserPasswordStore<User, int> instead of just IUserPasswordStore<User>.
Briefly:
public class CustomUserManager : UserManager<User, int>
{
public CustomUserManager(CustomUserStore store) : base(store)
{
}
}
public class CustomUserStore : IUserPasswordStore<User, int>
{
private readonly DbContext _db;
public CustomUserStore(DbContext db)
{
_db = db;
}
public Task<User> FindByIdAsync(int userId)
{
return _db.users.SingleOrDefaultAsync(u => u.Id == userId);
}
public Task UpdateAsync(User user)
{
_db.Entry(user).State = System.Data.Entity.EntityState.Modified;
return _db.SaveChangesAsync();
}
}
Now, it seems that when I call UpdateAsync on CustomUserManager, it does not go through my custom CustomUserStore, but rather through some default implementation or something. The problem is evident because CustomUserManager.UpdateAsync() returns Task<IdentityResult>, while my implementation in CustomUserStore returns just Task. Hence there are no errors or anything, but the method is not being called. I think IUserPasswordStore<User, int> should have some method UpdateAsync that returns Task<IdentityResult> but it doesn't...
On the other hand, the FindByIdAsync method does work fine and calls the method in my CustomUserStore.
I am quite sure the problem is due to inheriting the classes with the custom key type (int in my case). Any example of a custom UserStore I can find online just uses the string keys and does not inherit IUserStore<User, int> but just IUserStore<User>.
However I can't figure out my problem. Perhaps I can just override all the methods in my CustomUserManager but that seems like a work-around rather than a solution. Is this a bug in the framework perhaps, I think the custom key types is still relatively new or even in alpha?
I know that this is an old question but I struggled yesterday with the same issue and after some time spent on it, I decided to take a look in the Identity source code and what I've found, almost made me smashed my head against the wall...
Simple, if you call UserManager.UpdateAsync, in the base class you will see that before the UserStore.UpdateAsync there is a validation that takes place, which, in my case, failed (doesn't matter the reason). So, please, be so kind and check in your class (controller class) the result of UpdateAsync which is an IdentityResult and more then sure the Succes result is false.
Evdin

Wicket and Reusable Link

'm trying to create a reusable link class that extends Link. I have a webpage with about 7 menu items and I'm using inheritance for my application. I want to create a reusable link class to shorten the length of my code..
As of now the link creates and runs fine when I add(new Link....) as an anonymous class inside oninitialize().
The custom link class (which is an inner class of the base page) works fine when I hard code the instance of the new page to go to, and assign it to a "Page" reference, then pass it into setResponsePage();
The problem is, I'm passing trying to be able to pass object through the constructor generically. When I pass it through the constructor, and try to travel to the new page, I get a session has expired.
I've tried using generics for the class, and I've also tried just declaring a Page reference as a parameter value. Am I supposed to use some sort of Model? Or can someone provide an example of how to do this? I want to be able to use this custom link class to add new links for the 7 menu items, which each have there own class...
Code that works:
add(new Link("userPageLink")
{
public void onClick()
{
pageTitle = "User";
Page next = new UserPage();
setResponsePage(next);
}
});
Modified code that gives page expired upon click:
public class CustomLinkToNewPage extends Link
{
private String title;
private Page next;
public CustomLinkToNewPage(String id, String title, Page newPage)
{
super(id);
next = newPage;
this.title = title;
}
#Override
public void onClick()
{
SSAPage.pageTitle = title;
setResponsePage(next);
}
}
This might be due to the fact that in the first version you crate the Page object when the onClick method of the Link object is called and in the second version, the Page object is created on Page-construction (way earlier).
You might get the result if you pass the Pageclass of the responsepage instead on an instance.
Component features setters for these either with
public final <C extends IRequestablePage> void setResponsePage(java.lang.Class<C> cls, PageParameters parameters)
or without parameters.
public final <C extends IRequestablePage> void setResponsePage(java.lang.Class<C> cls)
See Javadoc for more information.
I ended up doing:
public class CustomLinkToNewPage<T extends SSAPage> extends Link
SSAPage is my base page that extends WebPage... So any object passed in to this class's constructor must extend SSAPage as well.
public CustomLinkToNewPage(String id, Class<T> name)
Then I passed in the .class reference to the object, and created a new instance of the object using reflection.. then set that instance to Page, and passed it to setResponsePage in my onClick. Worked nicely, as I couldn't figure out how to do Nicktar's way. So this an alternative in case anyone else runs into this issue.

Blackberry Application design question - Singletons

I'm refactoring a Blackberry application and I have a scenario where I think I'm currently using a global variable, but I'm not sure if that's the right thing to do. Briefly, my scenario is the following -
My app first requires the user to login. The (uid, pass) are sent to a web service which determines if the login is valid and returns some additional data. I have a model object on my application that looks something like this - (After a succesfully calling login)
class UserDataModel
{
private String username;
private String password;
private String fullName;
private String age;
...
/* Getters and Setters */
}
I also have a UserPreferencesModel which contains all the preferences that the user has saved. (I need to back them up to our database / restore them across devices etc.)
Additionally, in what context are Globals generally used in the context of mobile development?
Thanks,
Teja.
Well, I made a simple example how you can to use the RuntimeStore, I hope that this be of helpful
public class myData
{
long ID = 0xf46f5a7867d69ff0L;
String d1;
RuntimeStore runTS = RuntimeStore.getRuntimeStore();
public void setData(String _d1)
{
try
{
syncronized (runTS)
{
runTS.put(ID, _d1);
}
}catch(Exception ex){}
}
public String getData()
{
String s;
try
{
s = (String)(RuntimeStore.getRuntimeStore().get(ID));
}catch(Exception ex){}
return s;
}
}
There is nothing particularly special about BlackBerry in regards to using singletons. Of course, true constants should be just statics. And all of them should be final but Strings: there is a memory usage penalty if a static final String is reused often in your code.
What singleton gives you is the ability to replace or remove complex models with relatively long lifetime via a single point of control.
In your example, DataModel is a good candidate. BlackBerry is a personal device, so there is a big chance this DataModel with user profile and, probably, additional data, will survive for the lifetime of the active application.
So,
class UserDataModel
{
private static UserDataModel singleton;
public static void login() {
//get credentials
//authenticate
singleton = new UserDataModel(... user profile data...);
}
public static UserDataModel getInstance() { return singleton; }
private String username;
private String password;
private String fullName;
private String age;
...
/* Getters and Setters */
}
This way of doing it is a valid, a little simplified, example. If something changes (say, server host), all you need to do is to replace singleton. Also, it opens up a possibility to use polymorphism, if UserDataModel implementation is different for different servers, etc. There are many benefits to it at the cost of one extra variable in a chain of accessors. Again, there is nothing special about BlackBerry here, this reasoning is valid in any Java application.
Why the example is simplified is because you need to think about threads. If there is even a remote chance that something somewhere will access getInstance() on a different thread than login(), you have to properly synchronize them (even though I was never able to break a simple object reference by accessing/updating it from different threads on BlackBerry).
their are some scenarios when having static variable is good idea. like for Constant String fields.
here is the link to blackberry official Best practice document for writing efficient code for blackberry platform.
Black Berry: Best Practices: writing efficient code

How do I use the persistent object store in Blackberry?

I want to create a simple CRUD application to test out the data handling capabilities of the Blackberry.
How do I create a simple save function?
In this example I'm storing a vector in the persistent store.
You have to come up with a store ID, which should be of type long. I usually create this by concating the fully qualified Application's Class name to some string that makes it unique with in my application.
//class Fields...
//Use the application fully qualified name so that you don't have store collisions.
static String ApplicaitonID = Application.getApplication().getClass().getName();
static String STORE_NAME = "myTestStore_V1";
long storeId = StringUtilities.stringHashToLong( ApplicationID + STORE_NAME );
private static PersistentObject myStoredObject;
private static ContentProtectedVector myObjects;
//End class fields.
Example of loading a Vector from the store:
myStoredObject = PersistentStore.getPersistentObject( storeId );
myObjects = (ContentProtectedVector) myStoredObject.getContents();
//Print the number of objects in storeage:
System.out.println( myObjects.size() );
//Insert an element and update the store on "disk"...
myObjects.addElement( "New String" );
myStoredObject.setContents(myObjects);
myStoredObject.commit();
Example of initializing this store and saving it to disk for the first time:
myStoredObject = PersistentStore.getPersistentObject( storeId );
myObjects = (ContentProtectedVector) myStoredObject.getContents();
if(myObjects == null)
myObjects = new ContentProtectedVector();
myStoredObject.setContents(myObjects);
myStoredObject.commit();
If you want to commit changes (aka save changes to disk), you need to repeat the bottom two lines. setContents(OBJ); and Commit().
You can store the following without having to do anything special:
java.lang.Boolean
java.lang.Byte
java.lang.Character
java.lang.Integer
java.lang.Long
java.lang.Object
java.lang.Short
java.lang.String
java.util.Vector
java.util.Hashtable
#see : http://docs.blackberry.com/en/developers/deliverables/17952/Storing_objects_persistently_1219782_11.jsp
To store your own Classes, they (and all sub classes) have to implement the "Persistable" interface. I recommend that you do this, as these stores get cleaned up automatically when your application is uninstalled. This is because the OS cleans stored objects up, when "any" referenced classname in the store no longer has an application associated with it. So if your store is only using Strings, it's never going to get cleaned up.

Resources