For our iOS application, we have the ability for the user to enter in simple key-value preferences that should persist in 6 other applications within the same app group. This means the user will not need to re-enter those preferences 6 more times each time they open the other applications. We do this simply by calling UserDefaults(suiteName:) which returns a dictionary that is collectively readable/writable in all 7 iOS applications, which is quite convenient and useful. Is there an Android java equivalent of this? We don't want all of our Android users being forced to enter in the same information 7 times. I have tried creating a file that would be world readable/writable but cannot seem to find an appropriate directory that can be accessed by all 7 applications.
I had to write a hack to achieve this functionality, which was not preferred, but the requirement was necessary. I followed some of the accepted answer in this thread as suggested by Morrison Chang, but ended up having to loop through and compare to see which preference file was updated most recently and then make the updates to the app running the code, accordingly.
public static SharedPreferences getSharedPreferences(Activity activity) {
SharedPreferences prefs = activity.getApplicationContext().getSharedPreferences(SHARED_PREFS_KEY,
Context.MODE_PRIVATE);
long lastUpdate = prefs.getLong("lastUpdate", 0);
Context packageContext;
for (String app : new String[] { "app1", "app2", "app3", "app4", "app5", "app6" }) {
try {
packageContext = activity.createPackageContext(SHARED_PREFS_KEY + "." + app, 0);
SharedPreferences sharedPrefs = packageContext.getSharedPreferences(SHARED_PREFS_KEY, Context.MODE_PRIVATE);
long sharedLastUpdate = sharedPrefs.getLong("lastUpdate", 0);
if (sharedPrefs != null && sharedLastUpdate > lastUpdate) {
SharedPreferences.Editor editor = prefs.edit();
editor.clear();
for (Map.Entry<String, ?> entry : sharedPrefs.getAll().entrySet()) {
if (entry.getValue() instanceof Boolean)
editor.putBoolean(entry.getKey(), (Boolean) entry.getValue());
else if (entry.getValue() instanceof Float)
editor.putFloat(entry.getKey(), (Float) entry.getValue());
else if (entry.getValue() instanceof Integer)
editor.putInt(entry.getKey(), (Integer) entry.getValue());
else if (entry.getValue() instanceof Long)
editor.putLong(entry.getKey(), (Long) entry.getValue());
else if (entry.getValue() instanceof String)
editor.putString(entry.getKey(), (String) entry.getValue());
}
editor.commit();
break;
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
return prefs;
}
Related
I’m messing around with this problem for a long time and I’m very clueless how to get this going.
I want to create an app for the Amazon firetv stick 4k max (Android 9 - API level 28), that monitors if one specific app is in the foreground (or gets opened).
Do you have any ideas how to get the packagename of the app that is currently running in the foreground and that's actually working on an Amazon firetv stick 4K Max?
I would really appreciate your help!
I have found a way that works for other Android 9 devices by using the UsageStatsManager, but that does not seem to work for the stick.
Here is what I tried:
public String packageInForeground() {
// Get the UsageStatsManager
UsageStatsManager usageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
// Get the usage events for the last 5 seconds
long currentTime = System.currentTimeMillis();
List<UsageStats> usageStatsList = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, currentTime - 5000, currentTime);
// Find the latest usage event
UsageStats latestUsageStats = null;
if (usageStatsList != null) {
for (UsageStats usageStats : usageStatsList) {
if (latestUsageStats == null || usageStats.getLastTimeUsed() > latestUsageStats.getLastTimeUsed()) {
latestUsageStats = usageStats;
}
}
}
// Get the package name of the current foreground app
String currentForegroundApp = latestUsageStats != null ? latestUsageStats.getPackageName() : "";
Log.d("Service", "Current foreground app: " + currentForegroundApp);
return currentForegroundApp;
}
There is also a way to use the ActivityManager, but it will only show my own packagename if my own app is in the foreground, but does not show the packagename of other apps, if I open them.
Here is what I tried:
public String packageInForeground() {
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
String packageName = "";
if (runningAppProcesses != null && runningAppProcesses.size() > 0) {
for (ActivityManager.RunningAppProcessInfo processInfo : runningAppProcesses) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
packageName = processInfo.processName.split(":")[0];
Log.d("LockService", "Package Name: " + packageName);
break;
}
}
}
return packageName;
}
I'm trying to develop a small Application for a Zebra handheld rfid reader and can't find a way to access the MemoryBank of the tag. My reader configuration is as follows:
private void ConfigureReader() {
if (reader.isConnected()) {
TriggerInfo triggerInfo = new TriggerInfo();
triggerInfo.StartTrigger.setTriggerType(START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE);
triggerInfo.StopTrigger.setTriggerType(STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_IMMEDIATE);
try {
// receive events from reader
if (eventHandler == null){
eventHandler = new EventHandler();
}
reader.Events.addEventsListener(eventHandler);
// HH event
reader.Events.setHandheldEvent(true);
// tag event with tag data
reader.Events.setTagReadEvent(true);
reader.Events.setAttachTagDataWithReadEvent(true);
// set trigger mode as rfid so scanner beam will not come
reader.Config.setTriggerMode(ENUM_TRIGGER_MODE.RFID_MODE, true);
// set start and stop triggers
reader.Config.setStartTrigger(triggerInfo.StartTrigger);
reader.Config.setStopTrigger(triggerInfo.StopTrigger);
} catch (InvalidUsageException e) {
e.printStackTrace();
} catch (OperationFailureException e) {
e.printStackTrace();
}
}
}
And the eventReadNotify looks like this:
public void eventReadNotify(RfidReadEvents e) {
// Recommended to use new method getReadTagsEx for better performance in case of large tag population
TagData[] myTags = reader.Actions.getReadTags(100);
if (myTags != null) {
for (int index = 0; index < myTags.length; index++) {
Log.d(TAG, "Tag ID " + myTags[index].getTagID());
ACCESS_OPERATION_CODE aoc = myTags[index].getOpCode();
ACCESS_OPERATION_STATUS aos = myTags[index].getOpStatus();
if (aoc == ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ && aos == ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) {
if (myTags[index].getMemoryBankData().length() > 0) {
Log.d(TAG, " Mem Bank Data " + myTags[index].getMemoryBankData());
}
}
}
}
}
When I'm scanning a tag I get the correct TagID but both myTags[index].getOpCode() and myTags[index].getOpStatus() return null values.
I appreciate every suggestion that might lead to a successful scan.
Thanks.
I managed to find a solution for my problem. To perform any Read or Write task with Zebra Handheld Scanners the following two conditions must be satisfied. Look here for reference: How to write to RFID tag using RFIDLibrary by Zebra?
// make sure Inventory is stopped
reader.Actions.Inventory.stop();
// make sure DPO is disabled
reader.Config.setDPOState(DYNAMIC_POWER_OPTIMIZATION.DISABLE);
You have to stop the inventory and make sure to disable dpo in order to get data other than the TagID from a Tag. Unfortunately this isn't mentioned in the docu for Reading RFID Tags.
I use this code to detect if developer options are enabled on a phone or not:
int developerOptions = Settings.Secure.getInt(this.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED , 0);
However, I tested this and it returns the wrong value on a small number devices (some Huawei phones and others...)
Is there another full proof way to detect if developer options are enabled in a device?
I tried this but it doesn't work (I don't want to use that method anyway because it's not elegant, I'm just testing around):
try
{
startActivityForResult(new Intent(android.provider.Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS), 8080);
finishActivity(8080);
// Developer options enabled
}
catch (Exception e)
{
// Developer options disabled
}
My app's minimum API level is 21.
I've taken a look at this question and other similiar ones on SO but I didn't find a fullproof solution. This is not a duplicate question.
You can't do it any more foolproof than Android itself does it:
public static boolean isDevelopmentSettingsEnabled(Context context) {
final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
final boolean settingEnabled = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
Build.TYPE.equals("eng") ? 1 : 0) != 0;
final boolean hasRestriction = um.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES);
final boolean isAdmin = um.isAdminUser();
return isAdmin && !hasRestriction && settingEnabled;
}
Your code was close, but didn't account for
Build.TYPE.equals("eng") ? 1 : 0)
Min API 17 tested on emulator
public boolean isDeveloperModeEnabled(){
if (Integer.valueOf(android.os.Build.VERSION.SDK) >= 17) {
return android.provider.Settings.Secure.getInt(getActivity().getApplicationContext().getContentResolver(),
android.provider.Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
}
return false;
}
Try the code below:
int devOptions = Settings.Secure.getInt(this.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
Build.TYPE.equals("eng") ? 1 : 0);
I am trying to create a pinned shortcut on the homescreen of my using ShortcutManager. I am able to create the pinned shortcut using the following code:
Intent i = new Intent();
i.setAction(Intent.ACTION_VIEW);
i.setData(Uri.parse("www.google.com"));
if (ShortcutManagerCompat.isRequestPinShortcutSupported(context)){
ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(context, "#1")
.setIntent(i)
.setShortLabel("label")
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_launcher))
.build();
ShortcutManagerCompat.requestPinShortcut(context, shortcutInfo, null);
}else{
L.v("Shortcut", "Pinned shortcuts are not supported!");
}
I am facing two issues:
There is no check to handle duplicate shortcuts. Every time I click on the button to create a shortcut, it creates a shortcut every single time and the home screen is getting filled by these shortcuts. Is there any way to check whether the shortcut already exists like:-
Intent i = new Intent();
i.setAction(Intent.ACTION_VIEW);
i.setData(Uri.parse("www.google.com"));
Intent installer = new Intent(); installer.putExtra("android.intent.extra.shortcut.INTENT", i); installer.putExtra("android.intent.extra.shortcut.NAME", "Shortcut name"); installer.putExtra("android.intent.extra.shortcut.ICON_RESOURCE", Intent.ShortcutIconResource.fromContext(getApplicationContext() , R.drawable.ic_launcher));
installer.putExtra("duplicate", false);
installer.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
sendBroadcast(installer);
The problem with this piece of code is that it is not working in android 8.0 and above but it handles duplication of shortcut correctly using the following code :-
installer.putExtra("duplicate", false);
I want to achieve the same using Shortcut Manager
When a shortcut is created using Shortcut Manager, the icon is duplicated like
I have looked at the solution provided here but no luck so far:-
Strange app icon duplication in pinned shortcut (Android O)
Any ideas??
You can get all current shortcuts by calling
List<ShortcutInfo> currPinned = shortcutManager.getPinnedShortcuts();
then add to Map or Set and iterate over them and if its already exist dont add it again
if (currPinned != null) {
for (ShortcutInfo shortcut: currPinned) {
currPinnedMap.put(shortcut.getId(), shortcut);
}
}
....
//iterate over you "new shortcuts" and check if the present already
if (currPinnedMap.containsKey(id)) {
continue;
}
// add really new ones
fun isPinnedShortcutsExits(context: Context, id: String): Boolean {
return when {
Build.VERSION.SDK_INT >= 30 -> {
context.getSystemService(ShortcutManager::class.java)
.getShortcuts(ShortcutManager.FLAG_MATCH_PINNED)
.any { it.id == id }
}
Build.VERSION.SDK_INT >= 25 -> {
context.getSystemService(ShortcutManager::class.java)
.pinnedShortcuts
.any { it.id == id }
}
else -> false
}
}
or
ShortcutManagerCompat.getShortcuts(this, ShortcutManagerCompat.FLAG_MATCH_PINNED)
.any { it.id == "xxx" }
I'm developing a plugin for my software that will manage Microsoft TFS. Each plugin operation(check out, create label, check in, etc.) has to be run individually. My checkout operation creates a workspace, downloads that workspace, and then deletes the workspace mapping, but leaves the files behind to be built or modified.
Now, once the files are modified I need to check them back in. Since I deleted the workspace already, I'll have to make a new one.
I'm having trouble making a PendingChange[] object from the files in the workspace. Could anyone give any samples on how this would be done?
This is the code I'm using to create my workspace, if it helps:
public Workspace createWorkspace(String pWorkspaceName, String pLocalPath, String pServerPath)
{
WorkingFolder[] foldersToMap = null;
if (pServerPath != null && pLocalPath != null)
{
final List<WorkingFolder> folderList = new ArrayList<WorkingFolder>();
folderList.add(new WorkingFolder(pServerPath, LocalPath.canonicalize(pLocalPath), WorkingFolderType.MAP, RecursionType.FULL));
foldersToMap = folderList.toArray(EMPTY_WORKING_FOLDER_ARRAY);
}
else if (pServerPath == null || pServerPath.isEmpty())
{
//throw
}
else if (pLocalPath == null || pLocalPath.isEmpty())
{
//throw
}
Workspace w =
mVersionControlClient.createWorkspace(foldersToMap, pWorkspaceName, VersionControlConstants.AUTHENTICATED_USER, VersionControlConstants.AUTHENTICATED_USER, null /*Comment*/,
WorkspaceLocation.SERVER, WorkspaceOptions.NONE);
return w;
}
Microsoft's documentation isn't great on the java sdk, so any help is appreciated.
P.S. If there's anything wrong with my question, or if you want clarification, leave a comment and let me know before you downvote, I'll get it fixed.
Workspace ws = vcc.getWorkspace(workspaceName, ownerName);
PendingSet pendings = ws.getPendingChanges();
for (PendingChange pending : pendings.getPendingChanges()) {
ItemType type = pending.getItemType();
/*Don't download if it is a Folder*/
if (type.getWebServiceObject().getName()
.equals("Folder"))
continue;
ChangeType change = pending.getChangeType();
Item item = vcc.getItem(pending.getServerItem());
String itemName = StringUtils.getItemName(item.getServerItem());
/*My business rule: can't download if isn't in Lock with owner*/
if (!change.toString().contains("(512): Lock")) {
returns.add(new Return("ERROR", "The object "
+ item.getServerItem()
+ " isn't in Lock with " + owner
+ "."));
continue;
}
String destinationFile = destinationPath + "\\" + itemName;
item.downloadFile(vcc, destinationFile);
}
Hope to be helpful.