I currently have code to share a variable between two entry points in my application. The variable is the iconCount variable used to indicate how many notices the user has which is displayed on the home screen beside the icon. The way I've managed to do this is with a singleton and it (seems) to work fine at the moment. The issue is now that I do not want those notices to reset to zero when I completely turn off and turn on the phone. Should there be 7 notifications, I want there to be 7 notifications even after a device restart. For this I apparently need a persistent store integration which I've researched for a while.
So far my code for the bare singleton is:
public class MyAppIndicator{
public ApplicationIndicator _indicator;
public static MyAppIndicator _instance;
MyAppIndicator () {
setupIndicator();
}
public static MyAppIndicator getInstance() {
if (_instance == null) {
_instance = new MyAppIndicator ();
}
return(_instance);
}
public void setupIndicator() {
//Setup notification
if (_indicator == null) {
ApplicationIndicatorRegistry reg = ApplicationIndicatorRegistry.getInstance();
_indicator = reg.getApplicationIndicator();
if(_indicator == null) {
ApplicationIcon icon = new ApplicationIcon(EncodedImage.getEncodedImageResource ("notificationsdemo_jde.png"));
_indicator = reg.register(icon, false, true);
_indicator.setValue(0);
_indicator.setVisible(false);
}
}
}
public void setVisible1(boolean visible, int count) {
if (_indicator != null) {
if (visible) {
_indicator.setVisible(true);
_indicator.setValue(count); //UserInterface.incrementCount()
} else {
_indicator.setVisible(false);
}
}
}
}
I have been using the blackberry tutorial to figure out how to implement the persistable storage: http://supportforums.blackberry.com/t5/Java-Development/Storing-persistent-data/ta-p/442747
Now before I go any further I must stress I'm very new to java development so my coding might be completely wrong, but here is what I've tried to do:
public void setVisible1(boolean visible, int count) {
if (_indicator != null) {
if (visible) {
_indicator.setVisible(true);
_indicator.setValue(count); //UserInterface.incrementCount()
StoreInfo info = new StoreInfo();
info.incElement();
synchronized (persistentCount) {
//persistentCount.setContents(_data);
persistentCount.commit();
}
} else {
_indicator.setVisible(false);
}
}
}
static {
persistentCount = PersistentStore.getPersistentObject(0xdec6a67096f833cL);
synchronized (persistentCount) {
if (persistentCount.getContents() == null) {
persistentCount.setContents(new Vector()); //don't know what to do with this?
persistentCount.commit();
}
}
}
private static final class StoreInfo implements Persistable{
private int iconCount;
public StoreInfo(){}
public int getElement(){
return (int)iconCount;
}
public void incElement(){
iconCount++; //persistently increment icon variable
}
public void resetElement(){
iconCount=0; //when user checks application
}
}
The code above doesn't work which I'd expect somehow because I'm having trouble implementing the persistent portion. If anyone has any idea or input on how to accomplish this any assistance would be helpful. And of course thanks in advance.
In the example they have a variable called _data that holds the StoreInfo class, so first of all you should be keeping the StoreInfo in some variable. To do this have something like the following in your static initializer:
persistentCount = PersistentStore.getPersistentObject(0xdec6a67096f833cL);
synchronized (persistentCount) {
if (persistentCount.getContents() == null) {
persistentCount.setContents(new StoreInfo());
persistentCount.commit();
}
}
_data = (StoreInfo)persistentCount.getContents();
Now when you want to update it and save to the PersistentStore you can have something like:
_data.incElement();
synchronized(persistentCount) {
persistentCount.setContents(_data);
persistentCount.commit();
}
Assuming you're going to only ever have one instance of StoreInfo it could be better to put the commit code into the modifier methods so you don't forget to save the new values to the PersistentStore.
Related
public class InventorySetDAO{
public LinkedList<CustomInventory> inventories = new LinkedList<>();
}
I am developing plugin that add/delete data in arraylist. and There's too much reference on the arrayList from other class.
Class InventoryItemModifier:
public class InventoryItemModifier {
InventorySetDAO inventorySetDAO;
public InventoryItemModifier(InventorySetDAO inventorySetDAO){
this.inventorySetDAO = inventorySetDAO;
}
public void addItem(ItemStack itemStack, ClickAction click, RequiredItems requiredItems) {
Bukkit.getPluginManager().callEvent(new ItemAddedEvent());
inventorySetDAO.getLastInventory().addItem(itemStack, click, requiredItems);
}
public void removeItem(ItemStack itemStack){
Bukkit.getPluginManager().callEvent(new ItemRemovedEvent());
inventorySetDAO.getLastInventory().removeItem(itemStack);
}
}
Class InventoryPlayerAccessor:
public class InventoryPlayerAccessor {
InventorySetDAO inventorySetDAO;
public boolean openPage(Player player) {
if (!inventories.isEmpty()) {
inventories.get(0).openInventory(player);
return true;
}
return false;
}
public boolean openPage(Player player, int index) {
if (!inventories.isEmpty()) {
if (index >= 0 && index < inventories.size()) {
inventories.get(index).openInventory(player);
return true;
}
}
return false;
}
}
I think there is risk of manipualte arrayList unproperly, so I think arrayList must be in a class and provide methods(add/insert/remove...) but if then there are too much responsibilities in that class.
I tried to seperate them into multiple classes, but it doesn't seem to solve this problem. is there a way to reduce reliance on arrayList, or efficient way to encapsulate arrayList?
To reduce each classes reliance on the underlying ArrayList (or just List), you could think about using the composite pattern instead of the DAO pattern. This would hide all/most of the logic to the InventorySet class.
class InventorySet {
private final List<CustomInventory> inventories = new ArrayList<>();
public void addItem() { }
public void removeItem() { }
}
Then, you can just keep your InventoryPlayerAccessor (maybe rename) but compose it of a InventorySet for easy access.
class InventorySetView {
void open();
}
Okay, so I am working on an app that will auto accept lyft request, but I am having a problem with my code not using performAction(AccessibilityNodeInfo.ACTION_CLICK); correctly.
public class AutoService extends AccessibilityService {
private static LyftAdapter lyftAdapter = new LyftAdapter();
// Automated Service (onAccessibilityEvent)
#TargetApi(16)
#Override
public void onAccessibilityEvent(AccessibilityEvent event)
{
AccessibilityNodeInfo source = event.getSource();
String lyftPackage = "com.lyft.android.driver";
String packageName = Tools.getPackage(source);
if (!packageName.equals(lyftPackage))
{
event.recycle();
return;
}
if (source == null)
{
event.recycle();
return;
}
processUI(event.getSource());
}
public void processUI(AccessibilityNodeInfo source)
{
source = getRootInActiveWindow();
if (Tools.getPackage(source).equals("com.lyft.android.driver") || Tools.getPackage(source).equals("me.lyft.android"))
{
if (!Lyft_Status.equals("OFFLINE"))
{
lyftAdapter.processEvent(source);
}
else
{
Log.v(TAG, "Can't process UI: " + Lyft_Status);
}
}
if (source != null)
source.recycle();
}
}
public abstract class RideshareAdapter {
public void processEvent(final AccessibilityNodeInfo source)
{
final StringBuilder sb = new StringBuilder();
processSubEvent(source, 0, sb);
final String string = sb.toString();
if (string == null)
{
Log.v(TAG, "String is NULL");
return;
}
processUIText(source, string.toLowerCase());
}
// PROCESS SECONDARY EVENT
private void processSubEvent(final AccessibilityNodeInfo source, final int n, final StringBuilder sb) {
for (int i = 0; i < n; ++i) {
sb.append("\t");
}
if (source != null)
{
sb.append(Tools.getText(source));
sb.append("\n");
final int childCount = source.getChildCount();
for (int j = 0; j < childCount; ++j) {
final AccessibilityNodeInfo child = source.getChild(j);
processSubEvent(child, n + 1, sb);
if (child != null) {
child.recycle();
}
}
}
}
// CLICK THE SCREEN
protected void clickScreen(AccessibilityNodeInfo source, final String text)
{
final AccessibilityNodeInfo s = source;
new Handler().postDelayed(new Runnable() {
List<AccessibilityNodeInfo> list = s.findAccessibilityNodeInfosByText(text);
#Override
public void run() {
for (final AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}, 1000);
}
}
public class LyftAdapter
extends RideshareAdapter
{
// LYFT ADAPTER
protected void processUIText(AccessibilityNodeInfo source, String text)
{
// RIDE REQUEST
if (text.contains("tap here to accept"))
{
clickScreen(source, "Tap here to accept");
{
}
The string comes out as (Just like it is shown):
Lyft
11 mins
away
Passenger Name
New
Tap here to accept
But for some reason, it triggers saying it is going to click on "Tap here to accept" textview, but it never actually does it. Any suggestions?
To be completely honest, your post is very difficult to read. You have functions that you have defined purely for organizational purposes and not because they are meant to be re-used. It makes it very difficult to parse and understand over the course of a StackOverflow post... Yet you did not provide enough for me to copy and paste and make sense of in Android Studio.
When you post code on StackOverflow you should go for a minimal replicating example and you ABSOLUTELY should remove your random Log calls. You may need them to help you understand what's happening, but hopefully WE do not :) and they just clutter things and make it more difficult to read your code. THIS BEING SAID, allow me to focus on one bit,
Note that I have cleaned up some of the poor style and debugging statements. Answers are in the code comments!
protected void clickScreen(final AccessibilityNodeInfo source, final String text)
{
new Handler().postDelayed(new Runnable() {
//Find ALL of the nodes that match the "text" argument.
List<AccessibilityNodeInfo> list = source.findAccessibilityNodeInfosByText(text);
#Override
public void run() {
//Non discrliminintly click them, whether they're buttons, or text fields or links... just click them and hope they do something.
for (final AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
//Delay it for a second AFTER the function has been called for no particularly good reason besides perhaps invalidating all of the nodes in the heirarchy... GOOD CALL!
}, 1000);
}
Given the above issues and the aforementioned generic code quality issues, it is difficult to provide a concise answer. This post leaves too many potential issues. Any provided answer would be a stab in the dark. I find it MOST likely that the problem is covered in my code comments, but it could most definitely be elsewhere. Also, my apologies for the sass!
All this being said, you might try this version of the function!
static void clickFirstMatchingNode(AccessibilityService service, final String text) {
final List<AccessibilityNodeInfo> list = service.getRootInActiveWindow().findAccessibilityNodeInfosByText(text);
for (AccessibilityNodeInfo node : list) {
//Check if the action completely successfully. Also, only click one of them. This is kind of an assumption, it also simplifies the logic. You can certainly write a version of this that clicks everything that matches!
if (node.performAction(AccessibilityNodeInfo.ACTION_CLICK)) return;
}
//If no node is successfully clicked Log some stuff!
Log.wtf(YourService.class.getName(), "Failed to click any nodes! WTF?: " + text);
}
NOTE: None of the above mentioned anything to do with your use of Accessibility APIs! I think that that is interesting.
I'm using preferences to save the sound settings in my game as a boolean value. However, when I first start the game, the boolean initializes to false (sound off), because I'm not initializing it elsewhere. I could initialize it to true in the create method, but then the game would just start with sounds on every time you start the game, and that would just defeat the purpose of preferences.
Otherwise it works fine, it's just that I want the boolean to initialize to true the first time you start the game and not every time you restart it.
Is there a way to do this with preferences or do I have to use some other kind of saving method?
Note: this is a desktop application
public Preferences getPreferences() {
if (preferences == null) {
preferences = Gdx.app.getPreferences("myPrefs");
}
return preferences;
}
private void generatePreferences() {
getPreferences().clear();
getPreferences().putBoolean("soundEnabled", true).flush();
getPreferences().putBoolean("notFirstLaunch", true).flush();
}
public void loadPreferences() {
if (!getPreferences().getBoolean("notFirstLaunch")) {
generatePreferences();
} else {
//read the prefs and do your stuff
}
}
I would suggest you a slightly different approach:
Firstly, I think that the perfect place to initialize prefs is create method of the main game class (the one that extends Game):
public void create () {
Prefs.initPrefs();
....other initialization....
}
Then, initPrefs method looks like:
private static final String MUSIC_ON = "music_on";
private static final String LANG = "lang";
public static void initPrefs() {
boolean needChange = false;
if (!pref.contains(MUSIC_ON)) {
pref.putBoolean(MUSIC_ON, true);
needChange = true;
}
//if no lang - select system default
if (!pref.contains(LANG)) {
String language = Locale.getDefault().getLanguage();
pref.putString(LANG, language);
needChange = true;
}
if (needChange) {
pref.flush();
}
}
And finally to toggle the music:
public static boolean isMusicOn() {
return pref.getBoolean(MUSIC_ON);
}
public static void toggleMusic() {
pref.putBoolean(MUSIC_ON, !isMusicOn());
pref.flush();
}
I know this is a few years old now but just in case anyone else was wondering.
I think what you need to do is add a default value to your getBoolean() method without calling flush().
In my game i have a method called isSoundOn() which i call when my sound button is created. The very first time you start your game after installing it, you probably wont have saved a preference which means that the method below has to default to something. if you add true to the getBoolean method then your game should initialize to true.
public boolean isSoundOn() {
return preferences.getBoolean("soundOn", true);
}
I've faced a problem on Galaxy Note (gt-n7000). It appeared that I can't pass data between two activities directly via startActivity(intent) due to some changed demands. So I've implemented a Singleton class:
public class IntentStack {
private static IntentStack instance;
private Map<String, Stack<Intent>> IntentMap = new HashMap<String, Stack<Intent>>();
public synchronized static IntentStack getInstance() {
if (instance == null) {
instance = new IntentStack();
}
return instance;
}
private synchronized Stack<Intent> getStack(String key) {
if (IntentMap.containsKey(key))
return IntentMap.get(key);
else
return null;
}
public synchronized Intent getTopIntent(String key) {
if (IntentMap.containsKey(key)) {
if (!getStack(key).isEmpty())
return IntentMap.get(key).pop();
else
return null;
} else {
return null;
}
}
public synchronized void addIntent (String key, Intent intent) {
Stack<Intent> newStack;
if (IntentMap.containsKey(key)) {
newStack = IntentMap.get(key);
} else {
newStack = new Stack<Intent>();
}
newStack.push(intent);
IntentMap.put(key, newStack);
}
public synchronized void clearIntents(String key) {
IntentMap.remove(key);
}
}
In my first activity I put a data in IntentStack like this:
IntentStack.getInstance().addIntent(Core.getIm().getClassName("photobill"), takePictureIntent);
In my second Activity I try to get an Intent:
Intent i = IntentStack.getInstance().getTopIntent(Core.getIm().getClassName("photobill"));
Where Core.getIm().getClassName(string) get its values from the Map, which is initialized on the Application start.
The problem is that Intent i is null but only on Galaxy Note (gt-n7000). On the other phones code works properly.
What could possibly cause such behavior? And what should I do to fix it?
Android does not guarantee that a static variable will retains its value. If the device starts to run short of resources (memory) it will "de-allocate" static variables. This could be you case.
To start, I would add log in
if (instance == null) {
//ADD LOG HERE
instance = new IntentStack();
}
to see if you are creating a new instance or not.
I have this Thread inside my Project which runs continously accepting new symbols
public class StreamThread extends Thread {
private Set<String> allSymbolSet = new HashSet<String>(Arrays.asList("USBC", "TCSD", "PCLJ"));
private PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>();
public void addSymbols(String str) {
if (str != null) {
priorityBlocking.add(str);
}
}
public void run() {
while (true) {
try {
while (priorityBlocking.peek() != null) {
String symbol = priorityBlocking.poll();
allSymbolSet.add(symbol);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
my question is , i want to access the variable allSymbolSet from another class
what will be the best approach to get access to this variable named allSymbolSet from anoter class , for this i have two choices
modify the access specifier of allSymbolSet from private to default .
Write a get Method which is supoused to return the Set
Please suggest me , what will be the good approach in this case ??
Best approach would be the getter method AND synchronize the access to the object allSymbolSet, something like this:
public Set<String> getAllSymbolSet() {
synchronized(allSymbolSet) {
return allSymbolSet;
}
}
and also synchronize the access to allSymbolSet inside your thread.
A few comments:
If you make the set non-private, some code could modify it (by mistake or on purpose) which could result in inconsistent behaviour in your StreamThread class. Don't do that.
Providing a simple getter does not solve the issue above. Prefer returning a copy of your set.
Make your variables final whenever you can when in a multi-threading environment - it solves many thread safety issues.
Prefer implementing Runnable than extending Thread
You will need to synchronize ALL accesses to your set (read and write), for example by using a synchronizedSet or even better by wrapping a ConcurrentHashMap which generally provides better performance.
instead of peek+poll you can simply take from your queue
So your final class could look like:
public class StreamTask implements Runnable {
private final Set<String> allSymbolSet;
private final PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>();
public StreamTask() {
String[] symbols = {"USBC", "TCSD", "PCLJ"};
//use a thread safe set, for example based on ConcurrentHashMap
allSymbolSet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean> ());
Collections.addAll(allSymbolSet, symbols);
}
public void addSymbols(String str) {
if (str != null) {
priorityBlocking.add(str);
}
}
public Set<String> getSymbols() {
return new HashSet<> (allSymbolSet); //return a copy
}
public void run() {
while (true) {
try {
allSymbolSet.add(priorityBlocking.take());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Finally, I might be missing something, but that class looks equivalent to the much simpler:
public class StreamTask {
private final Set<String> allSymbolSet;
public StreamTask() {
String[] symbols = {"USBC", "TCSD", "PCLJ"};
//use a thread safe set, for example based on ConcurrentHashMap
allSymbolSet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean> ());
Collections.addAll(allSymbolSet, symbols);
}
public void addSymbols(String str) {
if (str != null) {
allSymbolSet.add(str);
}
}
public Set<String> getSymbols() {
return new HashSet<> (allSymbolSet); //return a copy
}
}
Better way is method 2. Writing a getter method. If you want to allow set the values then use a setter later. Then your data will be encapsulated .
Write a get Method which is supposed to return the Set. by using this your private remains private and you also access it from outside using Object of the same class.