I'm trying to implement Data Backup into my application. I build Android 2.2 project, and run in Galaxy s2 4.0.3.
I try to use: BackupManagerTest to save preferences to the cloud
This is my code :
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.amdroid.backuptest"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
<application
android:allowBackup="true"
android:backupAgent="net.amdroid.backuptest.MyBackupAgent"
android:icon="#drawable/icon"
android:label="#string/app_name" >
<activity
android:name=".BackupManagerTestActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAI7_yf1xqlpltWZPZiKMHVlDgn3nMfgotjUweSUg" />
</application>
</manifest>
MyBackupAgent.java
public class MyBackupAgent extends BackupAgentHelper {
// The names of the SharedPreferences groups that the application maintains. These
// are the same strings that are passed to getSharedPreferences(String, int).
static final String PREFS_TEST = "testprefs";
// An arbitrary string used within the BackupAgentHelper implementation to
// identify the SharedPreferenceBackupHelper's data.
static final String MY_PREFS_BACKUP_KEY = "myprefs";
// Simply allocate a helper and install it
#Override
public void onCreate() {
SharedPreferencesBackupHelper helper =
new SharedPreferencesBackupHelper(this, PREFS_TEST);
addHelper(MY_PREFS_BACKUP_KEY, helper);
Log.d("Test", "Adding backupagent...");
}
}
My Activity
public class BackupManagerTestActivity extends Activity {
private SharedPreferences prefs;
private Editor edit;
private BackupManager backupManager;
private EditText text;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
backupManager = new BackupManager(getBaseContext());
prefs = getSharedPreferences(MyBackupAgent.PREFS_TEST, Context.MODE_PRIVATE);
edit = prefs.edit();
text = (EditText) findViewById(R.id.editName);
String nome = prefs.getString("KEY_NAME", "");
text.setText(nome);
Button button = (Button) findViewById(R.id.buttonSave);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
edit.putString("KEY_NAME", text.getText().toString());
edit.commit();
Log.d("Test", "Calling backup...");
backupManager.dataChanged();
}
});
}
}
So MyBackupAgent never called. I don't know the reason.
When you call backupManager.dataChanged(), it merely schedules your app for backup. It does not mean your backup helper is called right away.
From http://developer.android.com/guide/topics/data/backup.html:
You can request a backup operation at any time by calling dataChanged(). This method notifies the Backup Manager that you'd like to backup your data using your backup agent. The Backup Manager then calls your backup agent's onBackup() method at an opportune time in the future. Typically, you should request a backup each time your data changes (such as when the user changes an application preference that you'd like to back up). If you call dataChanged() several times consecutively, before the Backup Manager requests a backup from your agent, your agent still receives just one call to onBackup().
Note: While developing your application, you can request a backup and initiate an immediate backup operation with the bmgr tool.
Instructions for the bmgr tool can be found at:
http://developer.android.com/tools/help/bmgr.html
To force all pending backup operations to run immediately, use:
adb shell bmgr run
Related
i don´t know where i have to setup the initial value of this variable:
mySharedPreferences.putStringValue("hello", "400");
And it don´t be reset if it is changed every time i open the app.
Thank you!!
The best way to do that is to "set" the default value on get method instead of set it on the first start of your app.
mySharedPreferences.getString("hello", "400");
On this way android checks if there was an value set. If not, it will fallback to the default "400".
Take a look at the documentation:
https://developer.android.com/reference/android/content/SharedPreferences.html#getString(java.lang.String, java.lang.String)
And in application tag
<application
android:name=".YourApplication"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
In Application's onCreate Method. It is best place. It will be executed when your app is created.
public class YourApplication extends Application {
public static Boolean sAppOpened = false;
#Override
public void onCreate() {
super.onCreate();
//Write your code here
sAppOpened = true;
....
}
...
}
Declare your SHARED PREFERENCE file name class-wide like this -
public static final String SHARED_PREFERENCES = "SHARED_PREF";
You can use this in your OnCreate method.
SharedPreferences sharedpreferences = getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE);
Editor editor = sharedpreferences.edit();
editor.putString("key", "value");
editor.commit();
I want to backup data in Android using MyBackUpAgent class which extends BackupAgentHelper. I am using SharedPreferences in order to store data.
My mainactivity code is:
public class MainActivity extends Activity {
EditText inputtext;
TextView outputtext;
Button submit;
public static SharedPreferences sharedprefs;
static final String File_Name_Of_Prefrences ="godplay_preferences";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
init();
sharedprefs=getSharedPreferences(File_Name_Of_Prefrences,MODE_PRIVATE);
System.out.println("value="+sharedprefs.getString("Input",""));
outputtext.setText(sharedprefs.getString("Input",""));
submit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
populateUI();
}
});
}
public void populateUI()
{
String savedinput=inputtext.getText().toString();
System.out.println("savedinput="+savedinput);
outputtext.setText(savedinput);
sharedprefs=getSharedPreferences(File_Name_Of_Prefrences,MODE_PRIVATE);
Editor editor=sharedprefs.edit();
editor.putString("Input",inputtext.getText().toString());
editor.commit();
requestBackup();
}
private void init() throws ClassCastException
{
inputtext=(EditText) findViewById(R.id.edtInputText);
outputtext=(TextView) findViewById(R.id.txtOutputText);
submit=(Button) findViewById(R.id.btnSubmit);
}
public void requestBackup() {
BackupManager bm = new BackupManager(getApplicationContext());
bm.dataChanged();
}
}
My MyBackUpAgent class:
public class MyBackUpAgent extends BackupAgentHelper{
static final String PREFS_BACKUP_KEY = "backup";
String key_string="Hello World";
#Override
public void onCreate() {
System.out.println("********************");
SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this,MainActivity.File_Name_Of_Prefrences);
addHelper(PREFS_BACKUP_KEY, helper);
}
}
My mainfest.xml file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.godplay"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:restoreAnyVersion="false"
android:backupAgent=".MyBackUpAgent"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.godplay.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="com.google.android.backup.api_key" android:value="AEdPqrEAAAAIhjloadYCTPUNo3yPsSX6LKmziiumZiQVlEEdBA" />
</application>
</manifest>
So far I have tried with bmgr tool to test, it is executing successfully with bmgr tool. However, on testing on Android device and emulator, back up is not happening, nor restoring.
Also, I have tested this on Android 5.1, Android 4.2, and Android 4.0 but still no luck.
It seems to me that my MyBackUpAgent class is never getting called, and I have tried breakpoints in MyBackUpAgent Class and validated it. Its never get hit.
What am I doing wrong?
Docs mention Conditions For Backup Schedule:
The user has enabled backup on the device in Settings > Backup & Reset.
At least 24 hours have elapsed since the last backup.
The device is idle and charging.
The device is connected to a Wi-Fi network. If the device is never connected to a wifi network, then Auto Backup never occurs.
If backup is working for you with bmgr tool but not on a real device / emulator, it's possible you are not meeting all those conditions, therefore backup never occur.
In your AndroidManifest.xml file, try changing
android:backupAgent=".MyBackUpAgent"
with the fully qualified class name, i.e.
android:backupAgent="com.abh.utils.MyBackUpAgent"
but of course changing "com.abh.utils" with the name of the package MyBackUpAgent.java is in.
I had a similar problem and have searched everywhere with no luck. Finally found the solution.
It seems that the BackupAgent needs to be in the top package with no preceding dot. So try changing:
android:backupAgent=".MyBackUpAgent"
to
android:backupAgent="MyBackUpAgent"
You can refer to developer document,
https://developer.android.com/guide/topics/data/backup.html#PerformingBackup
A backup request does not result in an immediate call to your onBackup() method. Instead, the Backup Manager waits for an appropriate time
you can use "bmgr tool" to initiate immediate backup whiling developing your app.
Make sure you call
adb shell bmgr run
to simulate the backup.
Also try using local transport to backup at any time:
adb shell bmgr transport android/com.android.internal.backup.LocalTransport
I'm trying to use SharedPreferencesBackupHelper to save my SharedPreferences value to cloud.
AndroidManifest.xml
<application
android:allowBackup="true"
android:backupAgent=".DataBackupAgent"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<meta-data android:name="com.google.android.backup.api_key" android:value="AEdPqrEAAAAIXMH86OqosQlXYuS0QbfyOaZT8fUadY1QUDzo2w" />
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
DataBackupAgent.java:
public class DataBackupAgent extends BackupAgentHelper {
public static final String PREFS = "data_prefs";
public static final String PREFS_BACKUP_KEY = "myprefs";
#Override
public void onCreate() {
SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS);
addHelper(PREFS_BACKUP_KEY, helper);
}
}
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
backupManager = new BackupManager(this);
prefs = getSharedPreferences(DataBackupAgent.PREFS, Context.MODE_PRIVATE);
edit = prefs.edit();
text = (EditText)findViewById(R.id.editText);
String value = prefs.getString(DataBackupAgent.PREFS_BACKUP_KEY,"");
text.setText(value);
Button btnBackup = (Button)findViewById(R.id.button);
btnBackup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
edit.putString(DataBackupAgent.PREFS_BACKUP_KEY,text.getText().toString());
edit.commit();
backupManager.dataChanged();
}
});
}
My steps:
Write something at the EditText, click Backup button
Close app and open again. The saved value will be shown in EditText
Uninstall the app and reinstall again. The saved value is not shown in EditText at all.
Edit at 27/02/2015:
I added the following code to restore manually:
backupManager.requestRestore(new RestoreObserver() {
#Override
public void restoreFinished(int error) {
super.restoreFinished(error);
String value = prefs.getString(DataBackupAgent.PREFS_BACKUP_KEY,"");
text.setText(value);
}
#Override
public void restoreStarting(int numPackages) {
super.restoreStarting(numPackages);
}
#Override
public void onUpdate(int nowBeingRestored, String currentPackage) {
super.onUpdate(nowBeingRestored, currentPackage);
}
});
Unfortunately no callback functions are called.
This means back or auto restore doesn't work at all. Any idea? Thanks
My steps:
1. Write something at the EditText, click Backup button
2. Close app and open again. The saved value will be shown in EditText
3. Uninstall the app and reinstall again. The saved value is not shown in EditText at all.
To test your implementation there are others steps related to the use of bmgras we can see here.
Nevertheless I implemented this feature some days ago and following the steps in the documentation using a real device - Samsung SII - the automatic restore doesn't happen BUT using the emulator all was fine.
Logcat will show you all the operation output details.
IMO, the Android Data Backup feature is not reliable today. We can see some discussion about the implementation problems here and here.
Hope it helps!
I try to implement low-frequency Live Card using the instruction provided in the GDK guides.
I have a layout that I want to render and the LiveCard service class (that extends Service). I also have the Menu: activity to handle menu callbacks, making the menu transparent, and provide a PendingIntent for the card's action using setAction() in the LiveCard service.
I also got a successful message when loading the app into Glass but it doesn't show up in my Glass.
I'm not sure what else is missing.
[2014-04-22 00:45:01 - MyApp] Installing MyApp.apk...
[2014-04-22 00:45:04 - MyApp] Success!
[2014-04-22 00:45:04 - MyApp] /MyApp/bin/MyApp.apk installed on device
[2014-04-22 00:45:04 - MyApp] Done!
Below is my LiveCardService:
public class LiveCardService extends Service {
private ArrayList<FeedItem> feedItems = new ArrayList<FeedItem>();
//private FeedAdapter feedAdapter = null;
// NYC: 40.758895, -73.985131
private double latitude = 0;
private double longitude = 0;
private LocationManager mlocManager;
private LocationListener mlocListener;
/******/
private static final String LIVE_CARD_TAG = "LiveCardDemo";
//private TimelineManager mTimelineManager;
private LiveCard mLiveCard;
private RemoteViews mLiveCardView;
private int homeScore, awayScore;
private Random mPointsGenerator;
private final Handler mHandler = new Handler();
private final UpdateLiveCardRunnable mUpdateLiveCardRunnable =
new UpdateLiveCardRunnable();
private static final long DELAY_MILLIS = 30000;
#Override
public void onCreate() {
super.onCreate();
//mTimelineManager = TimelineManager.from(this);
mPointsGenerator = new Random();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (mLiveCard == null) {
// Get an instance of a live card
// mLiveCard = mTimelineManager.createLiveCard(LIVE_CARD_TAG);
mLiveCard = new LiveCard(this, LIVE_CARD_TAG);
// Inflate a layout into a remote view
mLiveCardView = new RemoteViews(getPackageName(),
R.layout.score);
mLiveCard.setViews(mLiveCardView); // !!!
// Set up initial RemoteViews values
homeScore = 0;
awayScore = 0;
/**/
mLiveCardView.setTextViewText(R.id.homeTeamNameTextView,
/*getString(R.id.home_team)*/"HOME TEAM");
mLiveCardView.setTextViewText(R.id.awayTeamNameTextView,
/*getString(R.id.away_team)*/"AWAY TEAM NAME");
mLiveCardView.setTextViewText(R.id.footer_text,
/*getString(R.id.game_quarter)*/"FOOTER_TEXT");
/**/
// Set up the live card's action with a pending intent
// to show a menu when tapped
Intent menuIntent = new Intent(this, MenuActivity.class);
menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK);
mLiveCard.setAction(PendingIntent.getActivity(
this, 0, menuIntent, 0));
// Publish the live card
mLiveCard.publish(PublishMode.REVEAL);
// Queue the update text runnable
mHandler.post(mUpdateLiveCardRunnable);
}
return START_STICKY;
}
#Override
public void onDestroy() {
if (mLiveCard != null && mLiveCard.isPublished()) {
//Stop the handler from queuing more Runnable jobs
mUpdateLiveCardRunnable.setStop(true);
mLiveCard.unpublish();
mLiveCard = null;
}
super.onDestroy();
}
/**
* Runnable that updates live card contents
*/
private class UpdateLiveCardRunnable implements Runnable{
private boolean mIsStopped = false;
/*
* Updates the card with a fake score every 30 seconds as a demonstration.
* You also probably want to display something useful in your live card.
*
* If you are executing a long running task to get data to update a
* live card(e.g, making a web call), do this in another thread or
* AsyncTask.
*/
public void run(){
if(!isStopped()){
// Generate fake points.
homeScore += mPointsGenerator.nextInt(3);
awayScore += mPointsGenerator.nextInt(3);
// Update the remote view with the new scores.
mLiveCardView.setTextViewText(R.id.home_score_text_view,
String.valueOf(homeScore));
mLiveCardView.setTextViewText(R.id.away_score_text_view,
String.valueOf(awayScore));
// Always call setViews() to update the live card's RemoteViews.
mLiveCard.setViews(mLiveCardView);
// Queue another score update in 30 seconds.
mHandler.postDelayed(mUpdateLiveCardRunnable, DELAY_MILLIS);
}
}
public boolean isStopped() {
return mIsStopped;
}
public void setStop(boolean isStopped) {
this.mIsStopped = isStopped;
}
}
#Override
public IBinder onBind(Intent intent) {
/*
* If you need to set up interprocess communication
* (activity to a service, for instance), return a binder object
* so that the client can receive and modify data in this service.
*
* A typical use is to give a menu activity access to a binder object
* if it is trying to change a setting that is managed by the live card
* service. The menu activity in this sample does not require any
* of these capabilities, so this just returns null.
*/
return null;
}
and here is my Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.coeverywhere.google_glass"
android:versionCode="5"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />
<application
android:allowBackup="true"
android:icon="#drawable/mylogo"
android:label="#string/app_name">
<activity
android:name="com.myapp.google_glass.MenuActivity"
android:theme="#style/MenuTheme"
android:enabled="true"
>
</activity>
<!-- android:icon="#drawable/ic_lap" -->
<service
android:name="com.myapp.google_glass.LiveCardService"
android:label="#string/app_name"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/voice_trigger_start" />
</service>
</application>
</manifest>
and here's my voice_trigger_start.xml. I put them under res/xml
<?xml version="1.0" encoding="utf-8"?>
<trigger command = "basketball" />
Below is original answer, I have since made a reference project that takes the Google documentation and updates it for XE16 using the StopWatch project as a reference. Check the code and commit history to learn a lot more:
https://github.com/mscheel/GoogleGlass-XE16-LowFrequencyLiveCardBasketballScore
One way is to declare a voice trigger to start the service/livecard.
This is mentioned in this pattern explanation:
https://developers.google.com/glass/develop/patterns/ongoing-task
The technique is described here:
https://developers.google.com/glass/develop/gdk/starting-glassware#unlisted_commands
I tested it out with your code and it worked if the manifest has these items (modify for your package name of course) ... this first one goes inside the application tag:
<service
android:name="com.example.lowfrequencylivecardexample.LiveCardService"
android:enabled="true"
android:exported="true"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/voice_trigger" />
</service>
You also need:
<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />
You will also need this file ... res/xml/voice_trigger.xml:
<?xml version="1.0" encoding="utf-8"?>
<trigger keyword="basketball" />
I found the Timer project to be helpful in coming up with this, here is its manifest:
https://github.com/googleglass/gdk-timer-sample/blob/master/AndroidManifest.xml
Optionally you can make the home team the Celtics and the away team the Lakers. Larry Legend forever!
Im trying to do the backing up of my application's data into the Google Servers..
For doing this I've implemented a BackupAgent in my code and I included this in the Android Manifest file and "Meta-data" ( Got after registered my Application's package with the Android Backup Service)
When I run the application to do the backup this is not performing the backup.. Im using Nexus one device (connected to WIFI also) .
Could any one please let me know why it is not calling my BackupAgent's onBackup() method?
Am I missing some thing, to include in the Android manifest file or some where in the program?
The below is my manifest file..
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.simpledatabackup"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="#drawable/icon" android:label="#string/app_name"
android:backupAgent="MyBackupAgent"
android:debuggable="true">
<activity android:name=".SimpleDatabackup"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAIZn2ysSLR5wNbcq1uaoWQO0HuipMetQENVTsilw" />
</application>
<uses-sdk android:minSdkVersion="8" />
</manifest>
and the source file is
public class SimpleDatabackup extends Activity {
private SharedPreferences myPrefs ; // Shared Preferences
BackupManager mBackupManager;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myPrefs = this.getSharedPreferences("shared_prefs", MODE_WORLD_READABLE);
SharedPreferences.Editor edit = myPrefs.edit();
edit.putString("firstname", "uday") ;
edit.putString("lastname", "kiran") ;
edit.commit() ;
mBackupManager.dataChanged();
}
}
My Backup Agent is some thing like this: I have not implemented the functionality inside is onBackup() and onRestore(). Once if it is called i will implement what ever i want..
public class MyBackupAgent extends BackupAgent {
#Override
public void onCreate() {
System.out.println("In MyBackuAgent's onCreate() method");
}
#Override
public void onBackup(ParcelFileDescriptor arg0, BackupDataOutput arg1,
ParcelFileDescriptor arg2) throws IOException {
System.out.println("In MyBackuAgent's onBackup()");
// TODO Auto-generated method stub
}
#Override
public void onRestore(BackupDataInput data, int appVersionCode,
ParcelFileDescriptor newState) throws IOException {
}
}
In the application tag in the manifest include
android:allowBackup="true"
android:restoreAnyVersion="true"
android:backupAgent="<package>.MyBackupAgent"
Please follow the "Testing your BackupAgent" section to invoke the backup instantly for testing.
BackupManagerService schedules the backup regularly in hour interval after the datachanged call to backupmanager. [grepcode]