Backup/restore shared preferences android - java

I'm trying to backup/restore shared preferences of my app, I followed this step using Android Backup Service:
In Manifest.xml in <application> tag
<meta-data android:name="com.google.android.backup.api_key" android:value="My Key" />
added this class:
public class MyBackupAgent extends BackupAgentHelper {
// The name of the SharedPreferences file
static final String PREFS = "my_preferences";
#Override
public void onCreate() {
SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS);
addHelper(Utilities.SETTINGS_KEY, helper);
}
}
when set value to shared preference I do this:
BackupManager backupManager = new BackupManager(context);
backupManager.dataChanged();
But if I uninstall/reinstall app, changes doesn't apply...

My guess is you forgot to add
android:allowBackup="true"
inside your <application> tag in the AndroidManifest.xml file

You have to allocate a helper and add it to the backup agent like this:
#Override
public void onCreate() {
FileBackupHelper helper = new FileBackupHelper(this,
TOP_SCORES, PLAYER_STATS);
addHelper(FILES_BACKUP_KEY, helper);
}
and also consider overriding onBackup() and onRestore() methods.
See explanation here:
https://developer.android.com/guide/topics/data/keyvaluebackup.html#BackupAgentHelper

when you call dataChanged() you just notify system that something is changed, it does not start backup in this moment, give it some time and wi fi connection. Check in your device's settings under 'Backup and reset' if 'automatic restore' is set.
Make sure that you writing to the same preferences (with the same key) which you are saving context.getSharedPreferences("my_preferences", Context.MODE_PRIVATE);

I assume you have setting something like this (depends on android version and even on the device)
"Cloud and Accounts"->"Backup and Restore"->"Automatic restoration"
turned on. If not, turning it on may solve your problem.

Related

Does Android have an "onInstall" method?

I am trying to log installs of my app using Firebase with this simple code below:
firebaseAnalytics.logEvent("foo", bundle);
However, I am not sure where to put this code. Does any one know of an "onInstall" method in the Application class?
Or is there another, easier way to log installs with Firebase?
Thank you!
You could determine if the user launches the application for the first time, and log that event.
public class MyActivity extends Activity {
SharedPreferences prefs = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Perhaps set content view here
prefs = getSharedPreferences("com.mycompany.myAppName", MODE_PRIVATE);
}
#Override
protected void onResume() {
super.onResume();
if (prefs.getBoolean("firstrun", true)) {
firebaseAnalytics.logEvent("foo", bundle);
prefs.edit().putBoolean("firstrun", false).commit();
}
}
}
Code referenced from this SO answer.
There's another answer in that same SO question that explained how to differentiate between first run and subsequent upgrades, I'll just link that SO answer here for your reference.
The cleanest method would be to have a remote server that holds a unique ID for each user.
Also, you could theoretically write a file directly on the device. But then, you'd need to get the write permission and it's most definitely not a good idea to create and leave a file on the device.
P.S - To answer the actual question, No, Android doesn't have an onInstall method.

set shared preference default programmatically

I have a shared preference with no default value defined in the xml because I would like to set the default value programmatically when the main activity is created. The preference in question should either be the device language (if that language is available), otherwise the first available language, where the languages are defined in the appropriate xml as a string array.
I currently have, inside the main activity's onCreate method, the following
SharedPreferences preferences = getSharedPreferences(
getString(R.string.shared_prefs_key),
MODE_PRIVATE
);
String detailLanguage = preferences.getString(
getResources().getString(R.string.detail_display_language),
""
);
if (detailLanguage.isEmpty()) {
String deviceLanguage = Locale.getDefault().getLanguage();
String[] availableLanguages = getResources().getStringArray(R.array.pref_entry_values_detail_display_language);
boolean deviceLanguageSupported = false;
for (String availableLanguage : availableLanguages) {
if (deviceLanguage.equals(availableLanguage)) {
deviceLanguageSupported = true;
break;
}
}
preferences.edit()
.putString(
getResources()
.getString(R.string.detail_display_language),
deviceLanguageSupported ? deviceLanguage : availableLanguages[0]
).commit();
Debugging this code on the first run it enters the above if statement and sets the preference but the preference doesn't show as selected in the preference activity first time around (if I then select it myself, from then onward it appears selected as something).
Am I missing something? I am fairly new to Android. I tried the above based on some other similar SO questions.
PreferenceActivity and PreferenceFragment read preferences from a default preference file. To get access to those preferences you should use PreferenceManager.getDefaultSharedPreferences(context) method.
I am guessing that this is the reason you aren't seeing your changes: you write them to getString(R.string.shared_prefs_key) rather than to the default one.
Try changing your first line to this:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);

Android Copy & Paste to any text field in any application

I am developing an app for commercial use with a background service that is getting transponder numbers (of animals) from an RFID reader via bluetooth.
After processing the received number I would like to send it to the clipboard and paste it in the focused text field of whatever application is currently in front which in my case is a browser app.
I already found a similar question from 2013 but with no accepted answer by now. All answers to the question just explained how to use ClipboardManager to copy and paste code within the developed application but that has not been meant by the problem as he clarified in a comment.
The simplest scenario that I could imagine is to just simulate a paste action on the android device. I would prefer not to need to install a third party app.
Just to add to Kirill's answer and assuming the app has Accessibility permission,
Create a class extending AccessibilityService and override onAccessibilityEvent method.
public class SampleAccessibilityService extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
AccessibilityNodeInfo source = accessibilityEvent.getSource();
if (source != null) {
AccessibilityNodeInfo rowNode = getRootInActiveWindow();
if (rowNode != null) {
for (int i = 0; i < rowNode.getChildCount(); i++) {
AccessibilityNodeInfo accessibilityNodeInfo = rowNode.getChild(i);
if (accessibilityNodeInfo.isEditable() && accessibilityNodeInfo.isFocused()) {
accessibilityNodeInfo.performAction(AccessibilityNodeInfoCompat.ACTION_PASTE);
return;
}
}
}
}
}
#Override
public void onInterrupt() {
}
}
accessibilityNodeInfo.performAction(AccessibilityNodeInfoCompat.ACTION_PASTE) will paste the text that is copied to clipboard.
Also make sure you have right accessibility configuration.
config.xml
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityFlags="flagDefault"
android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
android:accessibilityFeedbackType="feedbackGeneric"
android:notificationTimeout="0"
android:canRetrieveWindowContent="true"
android:description="#string/testing" />
Here android:accessibilityEventTypes="typeViewClicked|typeViewFocused" will filter the events to view click or view focus.
You can also the events based on the packages using "android:packageNames" (so that your service won't get called often)
Finally declare the service in manifest,
<service android:name=".SampleAccessibilityService"
android:label="#string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/config" />
</service>
If you want your app to interact with an app that isn't yours (the browser) you will have to give this app accessibility permissions. those are special kind of permission that allow apps to interact with something that is a bit more senstive.
there are accessibility actions, the one that you are looking for is the
AccessibilityNodeInfoCompat.ACTION_PASTE it allows you to preform a paste into a focused field.
Note that I'd recommend you to replace the browser with a inapp WebView, and inject the values with javascript this will be much more robust solution for your automation. you can find more info on how to run JS on a webview here: How to get return value from javascript in webview of android?

Doing an action exactly once

I`m trying to add tracking events to my android app using Mixpanel (it simply tracks what actions the user is doing in an application), and I want to add an event called "Application Started".
The question is, where should I track the event of the app starting without having it repeated. Is there a method or a function call in the life cycle that executes when the app first starts and only once ?
Do it in onCreate() of your application class.. it will be done only once when app gets started...
No, application class is different from activities.. For an application, there can be only on application class.. And that you declare in the manifest file.. Typically like this:
public class MyApplication extends Application {
#override
onCreate()
{
// Do your task here..
}
}
You can save it in as a preference value:
SharedPreferences setting = PreferenceManager.getDefaultSharedPreferences(this);
boolean firstStart = setting.getBoolean("firstStart",true);
if(firstStart == true) {
//do work first time
SharedPreferences.Editor edit = setting.edit();
edit.putBoolean("firstStart", false);
edit.commit();
}

How to add custom view in android's JellyBean Launcher

I am working on making custom launcher in android. I have referred the code of android's Jellybean launcher. now I want to make some modification in this launcher.
What I want : As we know there are default five work-space screens and I want to add custom view in any one of the workspace screen. My xml file should be inflated in any one of the screen.
I have tried many ways to do it but as the default launcher code is very complex still having no luck to finding out way for it.
There is already app named SOHO in Playstore doing exactly what I want. I have add the screenshot for referencing what i want.
Please help me if anyone of you having any idea to do it.
I've the answer for you. You can do it both in Launcher2 and Launcher3 package from (AOSP). Jellybean is using Launcher2 may be. I personally suggest you to go with Launcher3, it has buit-in way to do so.
Launcher3:
create a class that extends the com.android.launcher3.Launcher class and override the necessary methods like so:
public class MyLauncher extends Launcher {
#Override
protected boolean hasCustomContentToLeft() {
return true;
}
#Override
protected void addCustomContentToLeft() {
View customView = getLayoutInflater().inflate(R.layout.custom, null);
CustomContentCallbacks callbacks = new CustomContentCallbacks() {
#Override
public void onShow() {}
#Override
public void onScrollProgressChanged(float progress) {}
#Override
public void onHide() {}
};
addToCustomContentPage(customView, callbacks, "custom view");
}
}
Here R.layout.custom is the custom view that you wanted.
Then in the manifest file change the launcher activity class from Launcher to MyLauncher. And that's it.
Launcher2:
in Workspace.java create the following method:
public void addCustomView(View child){
CellLayout layout = (CellLayout) getChildAt(0);
layout.addView(child);
}
then in Launcher.java, find the following line:
mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
then paste the following code somewhere after that line:
View child = LayoutInflater.from(this).inflate(R.layout.custom, null);
mWorkspace.addCustomView(child);
If I remember correctly you just need to implement a standard activity which displays a home launcher. In your Manifest.xml you just need to define it like this:
<activity android:name=".YourLauncher" android:label="#string/launcher_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
you can simply add view in default lanucher use code
wm = (WindowManager) getSystemService("window");
params = new LayoutParams();
params.type = LayoutParams.TYPE_PHONE;
params.format = PixelFormat.RGBA_8888;
params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE;
params.x = 100;
params.y = 100;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.gravity = Gravity.LEFT | Gravity.TOP;
wm.addView(view, params);
when you want to remove it
just
wm.removeView(v);
you also need permission
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Good news, not so good news, bad news. Good new first.
It is possible to do what you want.
Now the not so good news.
You will have to write the launcher application from scratch(aka Home Screen). Yep, that involves doing all those nice and nifty things that the default launcher does(multiple pages, drag and drop, delete/add app icons, etc). Fortunately, its not as difficult as it sounds. Because the default launcher app itself is opensource. Though this code is complete, its not easy to read. A easier place to start would be the SDK
Android-SDK/samples/android-x/Home/
where x is the API level.
They have provided source code for an example home screen and it should give you a good start. With some perseverance and coffee, you should be able to modify the Launcher2 code to add a customized page of your own.
Now the Hard part.
Because a part of your goal is to keep the existing pages same and add a new page, getting this to work for all the flavors of android... HTC sense, Samsung TouchWiz, etc, etc is not a single person workload. They all have different features for the Home screen. Preserving these features and adding a new customized page is a tough task.

Categories