Showing posts with label synctab. Show all posts
Showing posts with label synctab. Show all posts
SyncTab is open sourced
As I wrote yesterday on my twitter, SyncTab had been open sourced. About an year ago I started working on the project that would simplify my life. I used a lot my new smartphone to browse internet and read RSS, but the most interesting articles I wanted to read in my browser on laptop. And I can be pretty lazy and its easy for me to forget things, so I wanted to be sure that I won't leave this links without attention. The only way I could think about was just open the link in browser as soon as possible.
SyncTab architecture. Part 2. Android Application
This post is a continuation for recent post with description of SyncTab server application. In this post I'm going to tell about SyncTab Android application.
As android application is very simple, I will make a very short description.
SyncTab application has a few activities only: the main activity is a list of shared links. When user first opens an application, she can either login into or register a new account. There is also a way to reset a password. User can only reset password, as original password is not stored; only salted hash of the password is stored on server. After user is signed in, she can see the list of links, edit settings and tags etc.
When user is authenticated and device is online, application starts two services: SyncService and RefreshService.
RefreshService connects to the server and checks if there are any new links to open on this device. Each device has an associated tag and opens only links with specified tag. Android device by default checks for the links with Android tag, and opens them if any. By default, RefreshService checks the server every minute if connection is up. But it is possible to change a period time or disable this service at all (if user doesn't want to receive links on device).
SyncService is used to synchronize android application status with server. Application allows to send links, when device is offline. In this case, link can't be send, but is added to the sync queue. Well, there are other operations that can be proceeded offline, like logout, remove link, re-send link, add/edit/remove tags. If device is offline, such operations are added to the sync queue. When network is app and device is online, SyncService checks the sync queue and executes each task in it. Sync queue tasks are persistent and stored in the database.
No hard coded values, except preferences names. Everything moved to the appropriate files like strings.xml, array.xml, integers.xml, colors.xml etc. Values vary not only for different localization, but for different devices (e.g. phone and tablet).
Documentation is available only online from synctab website. Website has two versions: for normal clients and for mobile clients. While, my phone will be redirected to the mobile version, a tablet will open a normal version of website.
There are two managers for each entity, a regular manager and remote manager. Application works mostly with regular manager, which itself calls remote manager if need. For example, there are TagManager and RemoteTagManager. To call an operation, activities use SyncTabFacade, while SyncTabFacade calls managers.
Activities started using special IntentHelper class, that provides a static functions like
Links' favicons are cached as files in the cache directory. When a list of new links is retrieved, a favicon preloader thread starts. Thus, favicons are downloaded in background. If device is offline, and favicons can't be loaded, than an appropriate task is added to the sync queue for each favicon (and next time device is online, the favicons will be downloaded).
Well, looks like nothing interesting I can tell more about SyncTab android application.
So I decided to write a list of helpful facts about developing for Android as a separate post – "Tips: developing for Android".
As android application is very simple, I will make a very short description.
SyncTab application has a few activities only: the main activity is a list of shared links. When user first opens an application, she can either login into or register a new account. There is also a way to reset a password. User can only reset password, as original password is not stored; only salted hash of the password is stored on server. After user is signed in, she can see the list of links, edit settings and tags etc.
When user is authenticated and device is online, application starts two services: SyncService and RefreshService.
RefreshService connects to the server and checks if there are any new links to open on this device. Each device has an associated tag and opens only links with specified tag. Android device by default checks for the links with Android tag, and opens them if any. By default, RefreshService checks the server every minute if connection is up. But it is possible to change a period time or disable this service at all (if user doesn't want to receive links on device).
SyncService is used to synchronize android application status with server. Application allows to send links, when device is offline. In this case, link can't be send, but is added to the sync queue. Well, there are other operations that can be proceeded offline, like logout, remove link, re-send link, add/edit/remove tags. If device is offline, such operations are added to the sync queue. When network is app and device is online, SyncService checks the sync queue and executes each task in it. Sync queue tasks are persistent and stored in the database.
No hard coded values, except preferences names. Everything moved to the appropriate files like strings.xml, array.xml, integers.xml, colors.xml etc. Values vary not only for different localization, but for different devices (e.g. phone and tablet).
Documentation is available only online from synctab website. Website has two versions: for normal clients and for mobile clients. While, my phone will be redirected to the mobile version, a tablet will open a normal version of website.
There are two managers for each entity, a regular manager and remote manager. Application works mostly with regular manager, which itself calls remote manager if need. For example, there are TagManager and RemoteTagManager. To call an operation, activities use SyncTabFacade, while SyncTabFacade calls managers.
Activities started using special IntentHelper class, that provides a static functions like
showLoginActivity(), showAboutActivity(), browseDocumentation()
etc.Links' favicons are cached as files in the cache directory. When a list of new links is retrieved, a favicon preloader thread starts. Thus, favicons are downloaded in background. If device is offline, and favicons can't be loaded, than an appropriate task is added to the sync queue for each favicon (and next time device is online, the favicons will be downloaded).
Well, looks like nothing interesting I can tell more about SyncTab android application.
So I decided to write a list of helpful facts about developing for Android as a separate post – "Tips: developing for Android".
SyncTab architecture. Part 1. Server.
This post is a continuation for my previous post with introduction to SyncTab. I'm going to describe SyncTab server application in this post.
Well, I had a desire to write a server application on python, but in result I wrote it on Grails. Why Grails? Because I was actively using it for more than a year to creating different web applications, including web API. And I knew that would be simple and fast to create such app with Grails and publish some sort of web service.
So server side is running on a single Amazon EC2 instance. Application is running under Tomcat. Nginx plays a role of proxy. MongoDB is used as a database, and mongodb grails plugin used to add MongoDB.
API is very simple. It's based on GET/POST requests and JSON result with a status flag and other values, like auth token, list of tags and links.
Some code sample:
An authentication token system is used in SyncTab. Each time user enters his username/password to login, a new authentication token is created and assigned to user. Auth token is invalidated after two weeks.
As both Android application and Chrome extension should support not only login but also registration, it is a part of API too. Actually, user related API contains only 4 functions: register, authenticate, logout and resetPassword.
There are more API functions related to sending/receiving links and view/edit the list of tags.
A short about tags. Tags is just a way to name the device. For example, user can create a tag for his home computer and another tag for work computer, and tags for phone and tablet. Each device/browser is subscribed only to one tag, and will receive and open only links sent with specified tag.
Server not only responsible for storing and fetching links by client applications, but also for preparing links for user. Usually, when user sends a link, information about it contains only name of the device, tag id and the link URL. Server is responsible to fetch the link title, description, favicon link and the final URL. The final URL may differ from sent URL. For example, user could send a link like http://bit.ly/xNPUeo, but user should see this link as http://blog.khmelyuk.com.
Well, looks like there is nothing interesting left that I would like to tell about SyncTab server application.
Ah, source code is not public, and I'm not planning to open source it soon. As VCS I'm using Git and BitBucket as hosting service.
Well, I had a desire to write a server application on python, but in result I wrote it on Grails. Why Grails? Because I was actively using it for more than a year to creating different web applications, including web API. And I knew that would be simple and fast to create such app with Grails and publish some sort of web service.
So server side is running on a single Amazon EC2 instance. Application is running under Tomcat. Nginx plays a role of proxy. MongoDB is used as a database, and mongodb grails plugin used to add MongoDB.
API is very simple. It's based on GET/POST requests and JSON result with a status flag and other values, like auth token, list of tags and links.
Some code sample:
/** * Returns the list of last available tabs. * Client can pass a "tabId" parameter with an id of the tab to get tags for. * * Returns: * - status: "true" if was removed, otherwise "false". * - tabs: an array of found tabs. */ def getLastTabs = { if (request.method != 'GET') { response.sendError 405 return } User user = session.user Tag tag = getTagFromRequest() RecentTabConditions conditions = new RecentTabConditions(user, tag, LAST_TABS_NUM) Listtabs = sharedTabService.getRecentSharedTabs(conditions) render([status: true, tabs: prepareTabs(tabs)] as JSON) }
An authentication token system is used in SyncTab. Each time user enters his username/password to login, a new authentication token is created and assigned to user. Auth token is invalidated after two weeks.
As both Android application and Chrome extension should support not only login but also registration, it is a part of API too. Actually, user related API contains only 4 functions: register, authenticate, logout and resetPassword.
There are more API functions related to sending/receiving links and view/edit the list of tags.
A short about tags. Tags is just a way to name the device. For example, user can create a tag for his home computer and another tag for work computer, and tags for phone and tablet. Each device/browser is subscribed only to one tag, and will receive and open only links sent with specified tag.
Server not only responsible for storing and fetching links by client applications, but also for preparing links for user. Usually, when user sends a link, information about it contains only name of the device, tag id and the link URL. Server is responsible to fetch the link title, description, favicon link and the final URL. The final URL may differ from sent URL. For example, user could send a link like http://bit.ly/xNPUeo, but user should see this link as http://blog.khmelyuk.com.
Well, looks like there is nothing interesting left that I would like to tell about SyncTab server application.
Ah, source code is not public, and I'm not planning to open source it soon. As VCS I'm using Git and BitBucket as hosting service.
SyncTab architecture. Part 0.
A few months ago I was willing to write my own android application. And I also had a need - a way to send easily links from my phone to my browser and vice versa. Well, my phone is under Android, and my favourite browser is Chrome. So I decided to create the app to satisfy my desire to create and release Android app and make my life easier.
And as result of this, I have made a set of applications that forms a SyncTab. Obviously, those applications are Android application, server-side application and Chrome extension.
This post is like a preface, and next few posts will include a short technical description of each application.
Well, the work of application is very simple: android app and chrome extensions are both clients for the server. There is no web interface for application. User can get the list of all sent links and manage them using Android application.
In most functionality, Android app and Chrome extension are similar. But the only way to see the list of sent links is using Android application.
Some links:
And as result of this, I have made a set of applications that forms a SyncTab. Obviously, those applications are Android application, server-side application and Chrome extension.
This post is like a preface, and next few posts will include a short technical description of each application.
Well, the work of application is very simple: android app and chrome extensions are both clients for the server. There is no web interface for application. User can get the list of all sent links and manage them using Android application.
In most functionality, Android app and Chrome extension are similar. But the only way to see the list of sent links is using Android application.
Some links:
SyncTab
I've released today an updated version of a SyncTab Android application.
Well, a few words about what is a SyncTab. SyncTab is an application to send an interesting links and browser tabs from Android phone to desktop browser (current only Chrome is supported). To start using SyncTab, user need only to download and install Android application and Chrome extension. User will need to register an account using either Android application or Chrome extension and then he/she can easily send tabs from phone to desktop. There is more information about this in the Getting Started article.
So what's new in the version 0.6? Not much:
But I have more plans for version 0.7:
So try SyncTab now, and wait for a new features.
Well, a few words about what is a SyncTab. SyncTab is an application to send an interesting links and browser tabs from Android phone to desktop browser (current only Chrome is supported). To start using SyncTab, user need only to download and install Android application and Chrome extension. User will need to register an account using either Android application or Chrome extension and then he/she can easily send tabs from phone to desktop. There is more information about this in the Getting Started article.
So what's new in the version 0.6? Not much:
- added an about page to show current user name, website link, link to submit issue or contact
- get the correct page title and description with regards to the page charset
But I have more plans for version 0.7:
- share tabs from browser to the phone
- tag and filter shared tabs
So try SyncTab now, and wait for a new features.
Mobile website with jQuery Mobile
In my previous post I've described how to add support of mobile version of website using django. In this post I'm going to stop on front-end side of mobile website.
From the beginning, I wanted to create a simple mobile version from scratch and use a similar to original website look. But, after some investigation, I've changed my plans. I decided to use some framework to create a mobile website. So I found two popular such frameworks: Sencha Touch and jQuery Mobile. Whilst Sencha Touch looks awesome and production ready, while jQuery Mobile is still in release candidate stage, I stopped on the second one. This choice was very simple for me: jQuery products usually are qualitative, there is a strong community behind them and they introduce new versions very quick. Nevertheless Sencha Touch is a good product too.
I'm not going to describe how I used jQuery Mobile step by step, but only list of some facts and tips. First of all, I was using jQuery Mobile version 1.0 RC2, and that means, it wasn't a production-ready version yet. Even so, I found a few bugs or maybe just a things that need an improvement.
I just love such structures as lists. So will list a fact using a list =).
Well, that's all as for now. Hope that would be helpful.
From the beginning, I wanted to create a simple mobile version from scratch and use a similar to original website look. But, after some investigation, I've changed my plans. I decided to use some framework to create a mobile website. So I found two popular such frameworks: Sencha Touch and jQuery Mobile. Whilst Sencha Touch looks awesome and production ready, while jQuery Mobile is still in release candidate stage, I stopped on the second one. This choice was very simple for me: jQuery products usually are qualitative, there is a strong community behind them and they introduce new versions very quick. Nevertheless Sencha Touch is a good product too.
I'm not going to describe how I used jQuery Mobile step by step, but only list of some facts and tips. First of all, I was using jQuery Mobile version 1.0 RC2, and that means, it wasn't a production-ready version yet. Even so, I found a few bugs or maybe just a things that need an improvement.
I just love such structures as lists. So will list a fact using a list =).
- You should read a manual first and follow a standard layout mechanism, like declare header, content and footer sections. This will save you a lot of time.
<div data-role="page"> <div data-role="header"> <a href="{% url m_home %}" data-icon="home" class="ui-btn-left">Home</a> <a href="{% url m_help %}" data-icon="help" class="ui-btn-right">Help</a> {% block header %} <h1>[App Name]</h1>{% endblock %} </div> <div data-role="content"> {% block content %}{% endblock %} </div> <div id="footer" data-role="footer"> Copyright © 2011 ... </div> </div>
It's a good practice to add Home/Back and Help buttons to the header or footer panel. The navigation bar can be also added to the header, where it looks very natural:
<div data-role="header"> <a href="{% url m_home %}" data-icon="home" class="ui-btn-left">Home</a> <a href="{% url m_help %}" data-icon="help" class="ui-btn-right">Help</a> {% block header %}<h1>[AppName]</h1>{% endblock %} <div data-role="navbar"> <ul> <li><a href="{% url m_download %}">Download</a></li> <li><a href="{% url m_contact %}">Contact</a></li> ... </ul> </div> </div>
- Fixed position of header and footer isn't working as it's expected. Well, expected it to be fixed always, while content is scrolling. But currently it just disappears when user starts scrolling and shows back after a second or so scrolling is ended.
- Hash anchor links (#something) aren't working yet.
- Can't show an image as a page, instead shows an "undefined" text. If you have a links that reference images, you must specify
rel="external"
for them. - Use header to specify page title, rather than do it in the
h1
element in the content section. - Use collapsible blocks for long pages. For instance, I've found them very helpful to organize a help page with many different topics.
You may also want to embrace collapsible blocks using collapsible set. - For large image, don't show original version of it on page, but prefer thumbnail image as a link to the original version of image.
- Use list view where possible. For instance, a main help page contains a list of articles which are references to the appropriate pages.
- Buttons should be with icons where possible. You can easily add icon to the button with the
data-icon="[icon]"
attribute. The list of available icons is on jQuery Mobile website. - Make website as simple as possible: structure should be simple, navigation bar should contain only the most used links. Remember, that it's still hard to work fully with websites on mobiles.
Well, that's all as for now. Hope that would be helpful.
Mobile website with Django
Although I'm not a web guy, but more specialized on backend logic, I had a very interesting experience today creating a website version for mobiles. I had a simple website with a few pages, minimum server side logic and a slice of documentation there. This website perfectly works for desktop and tablet browsers, but is not that good for mobiles. I use to call this website as "normal" version throughout this post. It's important to have a working mobile version of website, as website is about Android application.
A little bit about technologies and task. Website is running on Django as well as mobile version should be too. Mobile version of website should be much simpler than normal version, not so beautiful, but must do own job well: allow users to know about the product, download and access to the documentation.
I decided to use the same django application for both normal and mobile website versions. I found a few different ways to add mobile website, for example: redirect to another django application, replace
Mobile website path should be prefixed with
I've created different templates and views for mobile version of website. Normal version of website has references only to the normal pages and mobile version of website has references only to the mobile pages. This was done to avoid not necessary redirects that could slow down a work with website. Thus, I had a different version of URL patterns for website in project's
Now need to redirect mobile browser users to the mobile version of website. For this purpose, I wrote a custom middleware called
If you'll check the list list of user agent patterns in
Now I have a simple website, that has two different version: one for desktop and tablet browsers and another for mobile browsers. User will be automatically redirected to the right version of website which depends on used device.
In my next post I'm going to tell more about using jQuery Mobile to build a mobile version of website.
A little bit about technologies and task. Website is running on Django as well as mobile version should be too. Mobile version of website should be much simpler than normal version, not so beautiful, but must do own job well: allow users to know about the product, download and access to the documentation.
I decided to use the same django application for both normal and mobile website versions. I found a few different ways to add mobile website, for example: redirect to another django application, replace
TEMPLATE_DIRS
setting with a version that points to mobile templates if user is using mobile browser or just check and use different logic/templates in every view method. As I wanted to have a different structure for mobile website, I decided to go by my own way.Mobile website path should be prefixed with
/m/
rather than be the same or use a different domain name. So, if normal website download page is http://example.com/download/
, then mobile download page should be http://example.com/m/download/
. Django should check every user request whether it's from mobile browser or not using a User-Agent metadata, and if so, redirect to the mobile version of the page. In other words, if user opens a /download/
page from mobile browser, then she will be redirected to the /m/download/
page. But if she opens a /m/download
page, then no redirects happen - just a mobile version of page is returned to user. I've created different templates and views for mobile version of website. Normal version of website has references only to the normal pages and mobile version of website has references only to the mobile pages. This was done to avoid not necessary redirects that could slow down a work with website. Thus, I had a different version of URL patterns for website in project's
urls.py
:urlpatterns = patterns('website.views', url(r'^$', 'home', name='home'), url(r'^download/$', 'download', name='download'), url(r'^screenshots/$', 'screenshots', name='screenshots'), url(r'^contact/$', 'contact', name='contact'), ... ) urlpatterns += patterns('website.mobile', url(r'^m/$', 'home', name='m_home'), url(r'^m/download/$', 'download', name='m_download'), url(r'^m/screenshots/$', 'screenshots', name='m_screenshots'), url(r'^m/contact/$', 'contact', name='m_contact'), ... )As you see,
website.views
are responsible for handling normal website pages, while website.mobile
for handling mobile website pages.Now need to redirect mobile browser users to the mobile version of website. For this purpose, I wrote a custom middleware called
MobileWebsiteMiddleware
. The task of this middleware is to check if user is from a popular mobile platform and needs to be redirected to the mobile version of website. The other responsibility is to redirect users from mobile to the normal version of website in case if request isn't from mobile browser. This is an extract option, that should be disabled while testing.class MobileWebsiteMiddleware(object): MOBILE_PREFIX = '/m/' MOBI_REG = re.compile( '(iphone|windows ce|mobile|phone|symbian|mini|pda|ipod|mobi|blackberry|playbook|vodafone|kindle)', re.IGNORECASE) def process_request(self, request): if 'HTTP_USER_AGENT' in request.META: userAgent = request.META.get('HTTP_USER_AGENT') matches = self.MOBI_REG.search(userAgent) path = request.path_info if matches: # from mobile browser, check if need to redirect to mobile if not path.startswith(self.MOBILE_PREFIX): # need to redirect to mobile version return HttpResponseRedirect('/m' + path) elif path.startswith(self.MOBILE_PREFIX): # need to redirect to normal version return HttpResponseRedirect(path[2:]) return None
If you'll check the list list of user agent patterns in
MOBI_REG
you wouldn't find neither iPad nor Android. I want to show a "normal" website for tablets. "Android" keyword is used in User Agent for both mobiles and tablets. While Mobile Android browsers pass a User Agent with a "mobile" keyword, but Tablet Android browsers don't do that. Thus, I will have a normal version for desktop and tablets browsers, but mobile version for mobiles and Kindle.Now I have a simple website, that has two different version: one for desktop and tablet browsers and another for mobile browsers. User will be automatically redirected to the right version of website which depends on used device.
In my next post I'm going to tell more about using jQuery Mobile to build a mobile version of website.
Subscribe to:
Posts (Atom)