How to backup and sync your rooted Android phone automatically

1 03 2012

I have for a while now been working on a custom automatic sync solution for my HTC Hero running Froyo (Froydvillain ROM). As I am a Linux junkie and love scripts and hacks I wanted to do it all via cunning hacks and I’ve finally got it nailed.

This solution uses Scripting Layer 4 Android (SL4A) and Tasker alongside a custom ROM with rsync (any ROM should do so long as it has rsync). For those that don’t know, rsync is an awesome application that allows for remote backup and sync across machines. It turns out you don’t even need a ROM with rsync built in, as you can install an app that provides rsync, the app is called rsync backup for android and can be found here: https://market.android.com/details?id=eu.kowalczuk.rsync4android&hl=en

The only issue is you can’t call rsync from the command line using simply “rsync” since it isn’t in your systems path. However, if you use the following string instead,replacing calls to “rsync” with the following, the scripts still work: /data/data/eu.kowalczuk.rsync4android/files/rsync

SL4A is used to set out what to do via a script. You can write scripts in various languages in SL4A but I am using Bash as I am familiar with it. Rsync is used to actually handle the sync / backup and Tasker is used to launch the scripts when certain conditions are met.

I have created two scripts in SL4A, one backups my photos folder to my main photo folder on my server. The server runs the rsync daemon which rsync on the phone connects to. The other script does the reverse and copies a remote folder in my server that contains a bunch of music to my phone.

Tasker is set up with a profile that activates when my phone is plugged in and it’s between midnight and 7.00 am. This then connects to my WiFi network and then runs the two scripts via the SL4A plugin. Since I charge my phone each night this is effectively automatic.

The key here is getting permissions correct with rsync during the file transfer, as the memory card uses fat32 it hasn’t got any permissions. The rsync daemon doesn’t like this and errors out, hence the need for various settings. The second key here is exporting your password as an environmental variable. This is inherently insecure but since my server has multiple redundant backups and is only locally accessible I don’t care much. I could use trusted keys but I’m too lazy.

Here are the two scripts. First the music script that syncs from server to phone:

#rsync sync
export RSYNC_PASSWORD=password
DATE=$(date)
LOG=/mnt/sdcard/rsyncmusic.txt
echo rsync started $DATE > $LOG
TRY=1
rsync_com ()
{
DATE=$(date)
if [ $TRY = 15 ]; then
echo rsync failed, quitting on $DATE >> $LOG
exit
fi
sleep 10
echo rsync attempt $TRY started $DATE >> $LOG
rsync --progress -vHrltD --chmod=Du+rwx,go-rwx,Fu+rw,go-rw --no-perms --stats --password-file=/mnt/sdcard/scrt prupert@prupert::amusic /mnt/sdcard/amusic >> $LOG 2>&1
EXIT=$?
TRY=`expr $TRY + 1`
echo exit code is $EXIT >> $LOG
echo "********************" >> $LOG
}
rsync_com
while [ $EXIT != 0 ]; do
rsync_com
done
echo rsync finished $DATE >> $LOG
exit

The second script syncs the phones photos folder to my server:

#rsync sync photo
export RSYNC_PASSWORD=password
DATE=$(date)
LOG=/mnt/sdcard/rsyncphoto.txt
echo rsyncphoto started $DATE > $LOG
TRY=1
rsync_com ()
{
DATE=$(date)
if [ $TRY = 15 ]; then
echo rsync failed, quitting on $DATE >> $LOG
exit
fi
sleep 10
echo rsync attempt $TRY started $DATE >> $LOG
rsync -vHrltD --chmod=Du+rwx,go-rwx,Fu+rw,go-rw --no-perms --stats --password-file /mnt/sdcard/scrt /mnt/sdcard/DCIM prupert@prupert::apics >> $LOG 2>&1
EXIT=$?
TRY=`expr $TRY + 1`
echo exit code is $EXIT >> $LOG
echo "********************" >> $LOG
}
rsync_com
while [ $EXIT != 0 ]; do
rsync_com
done
echo rsync finished $DATE >> $LOG
exit

I have put some logging in to check progress and also some retry code that retries the sync if it timesout. It seems my HTC Hero’s WiFi connection claps out after a while so the script retries up to 15 times to run successfully based on the rsync exit code.





get_iplayer startup script

19 02 2012

For funsies I am looking to create a web pvr, using get_iplayer, sickbeard and sabnzbd+ (though I am planning to stay on the legal side and only download what I can watch for free anyway).

Since there is no startup script for the get_iplayer web pvr program, I created one. You can find it here:

https://github.com/pruperting/code_snippets/blob/master/get_iplayer





XBMC Ubuntu Minimal Maverick Install Script

1 01 2011

As a little New Year’s present, I have updated a script that has been knocking around to allow you to install XBMC on a minimal version of Ubuntu Maverick.

If you simply install Ubuntu from the mini.iso containing the basic Ubuntu Maverick install, then on reboot, download my script using:

wget http://www.prupert.co.uk/scripts/xbmcmaverickrevo.sh

make it executable, using:

chmod a+x xbmcmaverickrevo.sh

then finally run it using:

sudo ./xbmcmaverickrevo.sh

I find it is best to run it again, once the script reboots the machine, as this fixes a few issues.

It is still a work in progress, as you can’t yet shutdown / restart etc via XBMC since it seems the method to add permissions in Ubuntu 10.10 have changed and they conflict with the setup here, so I am still looking into that. To shutdown / reboot at the moment, I log in via SSH and issue:

sudo shutdown -hP now

Also, it is designed to work just with the Acer Aspire Revo 3610, but there is no reason why it wont work with any other device (apart from maybe the audio configurations).

Enjoy.

Download It Here





FINALLY: A Bash Progress Indicator for ffmpeg that WORKS

11 05 2010

I decided to write a progress indicator for ffmpeg video conversions. This was much much much harder than I ever anticipated. I was in for a tough time. Annoyingly, for what ever reason, ffmpeg doesn’t use Carriage Returns and Line Feeds in the expected way when it outputs its output during a conversion, resulting in two days of stress for a noobie bashophile like me.

Eventually, after hours of googling, I came across the solution. This script should be a very accurate indicator of the progress of a ffmpeg video conversion. It currently only tells you how far the conversion has progressed as a percentage, but I will soon add an ETA and time to it as well (now added, see update below). It does this, by looking at the number of frames your input video file has, and then reading what frame ffmpeg is currently on every ten seconds, and printing out the percentage.

You have to put in your own ffmpeg command if you want, mine is just for converting .mpg DVB-T recordings from MythTV to mkv files.
To use the script, call the script with the full path of the file to be converted afterwards, e.g.: “./ffmpeg-progress.sh /home/prupert/FIVE.mpg” and it gives you something like this:

UPDATE:

I have now added an ETA function, which, as far as I can tell, should be pretty accurate, I’ll be testing it tomorrow to see how well it works. It is based on the remaining number of frames to process and the current fps that ffmpeg is working at. I also plan to convert the script to python, if possible, to make it cross platform and give it a GUI. It will also be called YAFF (Yet Another Ffmpeg Frontend).

Essentially, the script turns ffmpeg output from this:

frame=42992 fps= 21 q=29.0 size= 217692kB time=1717.72 bitrate=1038.2kbits/s dup=12 drop=0
frame=43002 fps= 21 q=29.0 size= 217692kB time=1718.12 bitrate=1038.0kbits/s dup=12 drop=0
frame=43018 fps= 21 q=29.0 size= 217756kB time=1718.76 bitrate=1037.9kbits/s dup=12 drop=0
frame=43036 fps= 21 q=29.0 size= 217788kB time=1719.48 bitrate=1037.6kbits/s dup=12 drop=0
frame=43050 fps= 21 q=29.0 size= 217820kB time=1720.04 bitrate=1037.4kbits/s dup=12 drop=0
frame=43062 fps= 21 q=29.0 size= 217852kB time=1720.52 bitrate=1037.3kbits/s dup=12 drop=0
frame=43078 fps= 21 q=29.0 size= 217884kB time=1721.16 bitrate=1037.0kbits/s dup=12 drop=0
frame=43090 fps= 21 q=29.0 size= 217916kB time=1721.64 bitrate=1036.9kbits/s dup=12 drop=0
frame=43106 fps= 21 q=29.0 size= 217948kB time=1722.28 bitrate=1036.7kbits/s dup=12 drop=0
Last message repeated 2 times
[mpeg2video @ 0x8f7ebf0]ac-tex damaged at 15 0
[mpeg2video @ 0x8f7ebf0]concealing 90 DC, 90 AC, 90 MV errors
frame=43122 fps= 21 q=29.0 size= 217981kB time=1722.92 bitrate=1036.4kbits/s dup=12 drop=0
frame=43140 fps= 21 q=29.0 size= 218045kB time=1723.64 bitrate=1036.3kbits/s dup=12 drop=0
frame=43155 fps= 21 q=29.0 size= 218077kB time=1724.24 bitrate=1036.1kbits/s dup=12 drop=0
frame=43168 fps= 21 q=29.0 size= 218141kB time=1724.76 bitrate=1036.1kbits/s dup=12 drop=0
frame=43182 fps= 21 q=29.0 size= 218205kB time=1725.32 bitrate=1036.1kbits/s dup=12 drop=0
frame=43194 fps= 21 q=29.0 size= 218237kB time=1725.80 bitrate=1035.9kbits/s dup=12 drop=0
frame=43207 fps= 21 q=29.0 size= 218269kB time=1726.32 bitrate=1035.8kbits/s dup=12 drop=0

In to this:

/home/rupert/Downloads/Village of the Damned.mpg..mpg has 172447 frames, now converting
ffmpeg PID = 24868
ffmpeg: 43062 of 172447 frames, progress: 24% and ETA: 1h 42m 41s

Which must be a good thing in anyone’s book ;)

The script is hosted at github, enjoy:

Creative Commons License
YAFF by Rupert Plumridge is licensed under a Creative Commons Attribution-Non-Commercial-Share Alike 2.0 UK: England & Wales License





Python Android Weather Forecast Script

28 04 2010

I am a proud owner of an HTC Hero Android phone.¬† I’ve recently¬† been messing around with one very cool looking application, that allows you to run your own scripts on the phone. This app is called Android Scripting Environment (ASE) and it is truly ace. You can use it to write and run your own Python, Shell (Bash), Lua and Ruby scripts directly on your phone. It also hooks into various Android features, allowing you to make use of various cool Android functions, one of which is getting your location and doing cool things with that information.

I’ve been wanting to get into Python for a long time and I decided that now was a good a time as any. ASE comes with a few sample scripts to get you going, one of which gets the current weather conditions for your current location and speaks it outloud (say_weather.py which calls weather.py). As cool as this is, being told the current conditions isn’t that useful, I wanted to know the forecast for the next day. I thus delved in and did lots of Googling, mainly using this awesome page that teaches you how to parse XML files (which is the format Google delivers its weather forecast info in). The biggest issue was the XML feed from Google doesn’t clarify the difference between the five day forecasts until you get to an actual data reading. The XML feed looks like this:

<xml_api_reply version="1">
      <weather module_id="0" tab_id="0" blah>
		<forecast_information>
			<city data="Bristol, Avon"/>
                        <postal_code data="bs167eb"/>
                        <latitude_e6 data=""/>
                        <longitude_e6 data=""/>
			<forecast_date data="2010-04-28"/>
                        <current_date_time data="2010-04-28 12:50:00 +0000"/>
                        <unit_system data="US"/>
		</forecast_information>
		<current_conditions>
			<condition data="Clear"/>
			<temp_f data="64"/><temp_c data="18"/>
			<humidity data="Humidity: 52%"/>
			<icon data="/ig/images/weather/sunny.gif"/>
			<wind_condition data="Wind: S at 16 mph"/>
		</current_conditions>
		<forecast_conditions>
			<day_of_week data="Wed"/>
			<low data="51"/>
			<high data="66"/>
			<icon data="/ig/images/weather/chance_of_rain.gif"/>
			<condition data="Chance of Rain"/>
		</forecast_conditions>
		<forecast_conditions>
			<day_of_week data="Thu"/>
			<low data="46"/>
			<high data="60"/>
			<icon data="/ig/images/weather/chance_of_rain.gif"/>
			<condition data="Chance of Rain"/>
		</forecast_conditions>
		<forecast_conditions>
			<day_of_week data="Fri"/>
			<low data="48"/>
			<high data="55"/>
			<icon data="/ig/images/weather/chance_of_rain.gif"/>
			<condition data="Chance of Rain"/>
		</forecast_conditions>
		<forecast_conditions>
			<day_of_week data="Sat"/>
			<low data="44"/>
			<high data="59"/>
			<icon data="/ig/images/weather/chance_of_rain.gif"/>
			<condition data="Chance of Rain"/>
		</forecast_conditions>
	</weather>

Now, I know nothing about XML at all, but I found it impossible to get the first actual forecast from the XML data, as each forecast was simply called “forecast_conditions”, using the method in the original weather.py. Thus, after reading the handy tutorial from faqs.org (listed above) I realised I needed to use the nested childNodes function of the xml.dom function that you use in Python to parse XML files.

After lots of trial and error, I worked out the following. A node is a name given to a section named via

<some_name>

. First, you assign a name (in this came dom) to the XML you are reading by doing: dom = minidom.parseString(xml_response), then I want to get information out of the node. To move through the nodes, you use the following command dom1Node = dom.firstChild where dom was the name of the original XML file. All this does is move to the first node and give it a name (dom1Node in my case), thus we are now at

<xml_api_reply version="1">

. You then use dom2Node = dom1Node.firstChild to move to the next node and give it a name, thus we are now at

<weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0">

. Finally, we have got somewhere, because the childNodes (i.e. the ones beneath the node we are at) are the ones with interesting info, such as

<forecast_information>

and most importantly

<forecast_conditions>

. So, finally, we can now assign names to these childNodes that we want. So we use current = dom2Node.childNodes[1] for the node (the numbering starts at 0 not 1) and forecast = dom2Node.childNodes[2] for the first forecast. Finally, to get the actual data out of those nodes, we use the following command data['flow'] = forecast.getElementsByTagName('low')[0].getAttribute('data'). What this does is give the name “flow” to the data element with the Tag name “low” from the “forecast” node that we defined just above. So, essentially, it navigates to and extracts the value “51” from it.

Thus, using this technique, you can get all the forecast data you want. I therefore ended up with this script, forecast.py, to replace the weather.py, to return forecast data:
And I then edited the say_weather.py to say the forecast as well as the current conditions, resulting in say_forecast.py:

The only problem I had with this was that the Google XML feed only appears to give the temp in fahrenheit, not celcius. I can see that you can set the iGoogle to display the temp in celcius, but I couldn’t see how to get that info from a feed.

Now, the next thing on the cards is to make a widget that displays this data on the homescreen. I was thinking of saving the output of the python script to a text file and then make a widget that reads that text file and displays the data. If I can do that, I can then modify the python script to do all sorts of cool things (get news, info from my mythtv HTPC etc).

Sadly, it seems on my version of Android (Cupcake (1.5)) you can’t call ASE scripts automatically via Locale or Tasker, since I get an ASE Force Closed message whenever I try to :( So these currently have to be run manually. Still, this is my first piece of Python coding and it was much easier than I thought it would be, once I got my head round it all.





Simple Bash Progress Script

21 04 2010

So, I wanted a way to monitor the progress of a Bash script I was running, since it could take a long time to run on occassion and I wasn’t sure if it had failed or not.

After some Ubuntu Forum googling, I came up with this:

#!/bin/bash
time=( $(tac /var/log/rsback/work-daily | grep -m 1 "total runtime" | awk '{ print $6 }') )
echo "last running time was" $time
/bin/rsback -v work-daily >> /var/log/rsback/work-daily &
pid=$!
trap "
#[ -e /proc/$pid ] && kill $pid
#" EXIT


while [ -e /proc/$pid ]; do
sleep 10
runtime=( $(ps ax | grep -m 1 zenity | awk '{print $4}') )
echo "#" $runtime
done | zenity --width 500 --progress --pulsate --title="work-daily running time: $time" --text="running time:" --auto-close
retval=$?


# If the progress bar was canceled, give a warning.
if [ $retval -ne 0 ]; then
zenity --title="work-daily rsback" --error --text="the work-daily rsback was cancelled" || exit 1
kill $pid
fi
time=( $(tac /var/log/rsback/work-daily | grep -m 1 "total runtime" | awk '{ print $6 }') )
zenity --info --title "Work rsback" --text "work rsback done in $time"
exit

It seems to work pretty well, though obviously this is customised for my particular needs (so it uses the command’s own log location etc). I thought I would share it with the world, since it took me a while to figure out. When I get the chance, I’ll update it to it can work with any command or script ;)





Automatically Update FFMPEG and x264 From Source / SVN In Ubuntu

16 04 2010

Whenever I wish to install and use the rather excellent video and audio transcode programs ffmpeg and x264 I have used FakeOutdoorsman’s excellent How To from the Ubuntu Forums. However, constantly typing out all the commands, especially when updating, is a pain in the arse.

I thus decided, with FakeOutdoorsman’s permission, to write some scripts to automate the task. They are, I hope, fairly comprehensive and allow a user to build and install the latest version of ffmpeg and x264, from source for Ubuntu Hardy, Intrepid, Jaunty, Karmic and Lucid. They allow this to be done automatically, after a few questions have been answered.

There are four scripts in total, one for the initial install, one for keeping everything up-to-date, one to reverse the changes with minimal impact and one to completely reverse all changes (this one I recommend no-one using, hence it is depreciated, but it is there in case some one wants it).

I am certainly not the best at bash, but I have done lots of Googling and I think the script is fairly robust, though I am sure there are errors.

I will be adding to the script over time, adding new features, combining things, adding better error checking etc, so for now consider them BETA releases. They have been tested on Lucid and Karmic only, but they appeared to work.

Please submit any questions here or at the project hosting page.

So, where are the files?

You can get all the scripts here:

http://code.google.com/p/x264-ffmpeg-up-to-date/

Have fun!








Follow

Get every new post delivered to your Inbox.