Best android questions in January 2012

Read Newer Theme Attributes On Older Platform

21 votes

I am trying to read attribute values from themes and styles which were designed for platforms that are newer than I am running my application on.

Please don't ask why. If you know anything about the libraries I write then you should already know that I like to push the capabilities of the platform :)

I am operating under the presumption that when Android styles are compiled the attribute constants are what is used for the keys and therefore should theoretically be able to be read on any platform somehow. This is what I have observed to be happening with layout XMLs in my other libraries with no trouble.

Here is a base test case which shows the problem. This should be compiled using Android 3.0+.

<resources>
    <style name="Theme.BreakMe">
        <item name="android:actionBarStyle">@style/Widget.BreakMe</item>
    </style>
    <style name="Widget.BreakMe" parent="android:Widget">
        <item name="android:padding">20dp</item>
    </style>
</resources>

The fact that this uses android:actionBarStyle specifically is irreleveant. All that should be understood is that its an attribute which was only available starting with Android 3.0.

Here are the way that I have tried to access these values thus far on platforms prior to Android 3.0.

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Break Me"
    style="?android:attr/actionBarStyle"
    />

and

<declare-styleable name="Whatever">
    <item name="datStyle" format="reference" />
</declare-styleable>

<style name="Theme.BreakMe.Take2">
    <item name="datStyle">?android:attr/actionBarSize</item>
</style>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Break Me"
    style="?attr/datStyle"
    />

and

TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.actionBarStyle, outValue, true);

and

int[] Theme = new int[] { android.R.attr.actionBarSize };
int Theme_actionBarSize = 0;
TypedArray a = context.obtainStyledAttributes(attrs, Theme);
int ref = a.getResourceId(Theme_actionBarSize, 0);

and

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar, android.R.attr.actionBarStyle, 0);

All of them result in this error in LogCat:

E/ResourceType(5618): Style contains key with bad entry: 0x010102ce

The 0x010102ce constant is the attribute value of android.R.attr.actionBarStyle which seems to indicate the platform is rejecting the attribute before I can even get a chance to access its value.

I am looking for any other way to read attributes like this from the Theme. I'm fairly sure that once I've obtained the style reference I won't have trouble reading its attributes.

Is there any possible way to do this?

I am operating under the presumption that when Android styles are compiled the attribute constants are what is used for the keys and therefore should theoretically be able to be read on any platform somehow.

Possibly, though that is not how I am interpreting the C++ source code that raises the error you are seeing. Check out ResTable::Theme::applyStyle() in frameworks/base/libs/utils/ResourceTypes.cpp.

My interpretation is that Android has what amounts to an in-memory table of packages->types->possible entries:

numEntries = curPI->types[t].numEntries;

Your entry index is higher than the highest known entry:

if (e >= numEntries) {
    LOGE("Style contains key with bad entry: 0x%08x\n", attrRes);
    bag++;
    continue;
}

It is possible that they handle this different for android versus other packages -- android uses known values at firmware build time (and your generated entry index is higher, because it is from a newer platform), non-android ones assume anything's valid.

If my guesswork is correct, what you want to do will not work. That being said, my C++ days are seriously in my rear-view mirror, so I may be misinterpreting what I'm seeing.

Good software engineering vs. Security

13 votes

The Security and Design guidelines go to great length outlining various methods to make it more difficult for an attacker to compromise in-app billing implementation.

Especially noted is how easy it is to reverse-engineer a .apk file, even if obfuscated via Proguard. So they even recommend modifying all sample application code, especially "known entry points and exit points".

What I find missing is any reference to the wrapping certain verification methods in a single method, like the static Security.verify() which returns boolean: A good design practice (reducing code duplication, reusable, easier to debug, self-documenting, etc.) but all an attacker needs to do now is identify that method and make it always return true... So regardless how many times I used it, delayed or not delayed, randomly or not, it simply doesn't matter.

On the other hand, Java doesn't have macros like in C/C++, which allows reducing source code duplication, but doesn't have a single exit point for a verify() function.

So my questions:

Is there an inherent contention between the well known software engineering/coding practices and design for so called security? (in the context of Java/Android/secure transactions at least)

What can be done to mitigate the side-effects of "design for security" which seems like "shooting oneself in the foot" in terms of over-complicating software that could have been simpler, more maintainable and easier to debug?

Can you recommend good sources for further studying this subject?

As usual, it's a tradeoff. Making your code harder to reverse-engineer/crack involves making it less readable and harder to maintain. You decide how far to go, based on your intended user base, your own skills in the area, time/cost, etc. This is not specific to Android. Watch this Google I/O presentation for various stages of obfuscating and making your code tamper resistant. Then decide how far you are willing to go for your own apps.

On the other hand, you don't have to obfuscate/harden, etc. all of your code, just the part that deals with licensing, etc. That is usually a very small part of the whole codebase and doesn't really need to change that often, so you could probably live with it being hard to follow/maintain, etc. Just keep some notes on how it works, so you remind yourself 2 years later :).

Application Not installed in your phone

11 votes

I run the application in the emulator it works successfully and the icon of the application is show in the emulator menu but when i try to run again that app from the emulator menu it can't allow me to run from that and display the Toast "Application is Not installed in your phone".

In the Image the red rounded is my application icon.

enter image description here

This can happen if you have your MainActivity declared twice in your AndroidManifest.xml,

first as a launhcer

<activity android:name=".MyActivity" android:label="@string/app_name">  
    <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

and then just declared like:

<activity android:name=".MyActivity" />

So check for this and delete the second extra declaration.

Is there any free C++ and/or C# compiler that runs on an Android-enabled Tablet PC?

10 votes

The question is not about writing C++ for Android, it's about writing C++ on Android.

I have an Android-enabled Tablet PC and I need to do both C++ and C# programming.

Is there any free C++ and/or C# compiler that runs on any Android-enabled Tablet PC?

I do not want to develop Android apps on PC.

I want to do my programming on an IDE that runs on Android.

It exists in some form, at least. I have managed to find an application that even compiles C and Delphi without any extra dependencies (I assume it comes with GCC and FreePascal.) I can't find it at the moment, but keep searching. In the meantime, TouchQode at least will give you some scripting support. For C#, you'll need Mono. The runtime for Mono is certainly available on Android and I see absolutely no reason there can't be a compiler for it on Android as well. edit: As CommonWares mentions, there is no freely available Mono port for Android, so none of this applies. Pity.

How to find out if a Skype call is currently active on Android

9 votes

Okay, I decompiled Skype's manifest to find out if there are any Services or Broadcasts running during a call. There are only a few internal broadcasts for incoming calls. Also only one receiver and one service exist.

I monitored all running services with my app, but the SkypeMainService is always running, even if not in a call.

Also AudioMode is not changed by skype (but according to the logcat-logs the dev wanted to, but they just don't do it), so I cannot simply check if it is MODE_IN_CALL.

Do you have any suggestions how to find out, if Skype is currently running and having an active call?

Thanks!

/edit: A brief overview of the Activities etc:

<activity android:name="com.skype.raider.Main">
<activity-alias android:name="com.skype.raider.ui.SplashScreenActivity" android:targetActivity="com.skype.raider.Main">
<receiver android:name="com.skype.MainReceiver" android:enabled="true" android:exported="false">
   <action android:name="android.intent.action.BOOT_COMPLETED" />
   <action android:name="android.intent.action.MEDIA_MOUNTED" />
   <action android:name="android.intent.action.SEARCH" />
   <action android:name="android.intent.action.CALL_PRIVILEGED" />
   <action android:name="com.skype.raider.INCOMING_GSM_CALL" />
   <action android:name="com.skype.raider.ON_GSM_CALL" />
   <action android:name="com.skype.raider.intent.action.request_sync" />
</receiver>
<service android:name="com.skype.MainService">

Okay, I really hoped someone would provide a useful answer. However, I picked up Reuben's advice in the comment and made this method:

/**
 * Gets the current activity
 * 
 * @param context
 *            A context to use
 * @return The Activity name
 */
public static String getCurrentTopActivity(Context context) {
    ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> RunningTask = mActivityManager.getRunningTasks(1);
    ActivityManager.RunningTaskInfo ar = RunningTask.get(0);
    return ar.topActivity.getClassName().toString();
}

Then I check if the result equals com.skype.raider.Main. This will also return true if there is no active Skype call, but the main app is open.

Thanks for all the help, especially Reuben!

Android: Java, C or C++?

9 votes

I wrote some simple apps in Android using Java.
But later I found this:

It provides headers and libraries that allow you to build activities, handle user input, use hardware sensors, access application resources, and more, when programming in C or C++. (Source)

How is it related to this:

Android applications are written in the Java programming language. (Source)

Are all three languages possible?
Sorry for the dumb question.

The article you link to has good information. It also links to http://developer.android.com/sdk/ndk/overview.html which says:

The NDK will not benefit most applications. As a developer, you need to balance its benefits against its drawbacks; notably, using native code does not result in an automatic performance increase, but always increases application complexity. In general, you should only use native code if it is essential to your application, not just because you prefer to program in C/C++.

Typical good candidates for the NDK are self-contained, CPU-intensive operations that don't allocate much memory, such as signal processing, physics simulation, and so on. Simply re-coding a method to run in C usually does not result in a large performance increase. When examining whether or not you should develop in native code, think about your requirements and see if the Android framework APIs provide the functionality that you need. The NDK can, however, can be an effective way to reuse a large corpus of existing C/C++ code.

LogCat not displaying TAG "SMS"

8 votes
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Log.e("SMS","Hello World");   //not showing
    Log.v("SMS","Hello World");   //not showing
    Log.i("SMS","Hello World");   //not showing
    Log.d("SMS","Hello World");   //not showing

    Log.i("sms","Hello World");   //showing
}

Why the Logging in the Logcat is not working for some line in the above code??

There are some tags that don't go to the default buffer, as has been stated.

You can view them by specifying which buffer to view with the "-b" logcat option. [Documentation] For example, to see the "SMS" logcat messages, start logcat with:

adb logcat -b radio

Keep a Service running even when phone is asleep?

8 votes

I have a Service in my application which is designed to run every 10 minutes. It basically checks up on our servers to see if everything is running properly and notifies the user of any problems. I created this application for internal use at our company.

My co-worker used the application over the long weekend and noticed that no checks were performed when the device went to sleep. I was under the impression that the Service was supposed to keep running in the background until I explicitly call stopService() in my code.

So ultimately, my goal is to have the service running until the user hits the off button in the application or kills the process.

I heard about something called WakeLock which is meant to keep the screen from turning off, which is not what I want. I then heard of another thing called a partial WakeLock, which keeps the CPU running even when the device is asleep. The latter sounds closer to what I need.

How do I acquire this WakeLock and when should I release it and are there other ways around this?

One way to do recurrent tasks is this:

  • Create a class AlarmReceiver

    public class AlarmReceiver extends BroadcastReceiver 
    {
        @Override
        public void onReceive(Context context,Intent intent) 
        {
            Intent myService = new Intent(context,YourService.class);
            context.startService(myService);
        }
    }
    

    with YourService being your service ;-)

  • Create a Pending Intent

To start your recurrent polling, execute this code in your activity:

Intent myAlarm = new Intent(getApplicationContext(),AlarmReceiver.class);
//myAlarm.putExtra("project_id",project_id); //Put Extra if needed
PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(),0,myAlarm,PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
//updateTime.setWhatever(0);    //set time to start first occurence of alarm 
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP,updateTime.getTimeInMillis(),AlarmManager.INTERVAL_DAY,recurringAlarm); //you can modify the interval of course

This code sets up an Alarm and a canceable pendingIntent. The alarmManager gets the job to repeat the recurringAlarm every day (third argument), but inexact so the cpu does wake up approximately after the inverval but not exactly (avoids battery drain). The first time the alarm (and thus the service) is started will be the time you choose to be updateTime

  • last but not least: here is how to kill the recurring alarm

    Intent myAlarm = new Intent(getApplicationContext(),AlarmReceiver.class);
    //myAlarm.putExtra("project_id",project_id); //put the SAME extras
    PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(),0,myAlarm,PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarms = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    alarms.cancel(recurringAlarm);
    

This code creates a copy of your (probably) existing alarm and tells the alarmManager to cancel all alarms of that kind.

  • of course there is also something to do in the Manifest:

include these two lines

  < receiver android:name=".AlarmReceiver"></receiver>
  < service android:name=".YourService"></service>

inside the < application>-tag. Without it, the system does not accept the start of recurrent alarm of a service.

The missing MENU button in HoneyComb and Ice Cream Sandwich

8 votes

I'm a fan of the menu button as used in Android <3.0, as it was very useful for my game apps - it allowed me to take important but gameplay irrelevant functionality (saving game, reference info links) and place it somewhere where it did not clutter up the main game interface, but was still easily accessible (the options menu).

This use of keys became a problem with 3.0, because it removed the MENU button and substituted it with the Action Bar. The Action bar is really not suitable for a game which likes to run full-screen, so that was a real pain. No action bar - no access to the options menu. However, I could sort of ignore it for a while, since I didn't have that many users on tablets and lacked the time to test this.

However, ICS makes this a serious issue, since the MENU button is obviously not coming back. Now I don't only have to deal with this problems on tablets, but on phones as well.

My initial solution to this problem has been to simply place a soft button in my GUI to replace the hard MENU button

this.openOptionsMenu();

And everything is back to working perfectly in ICS.

However, this does not work on Honeycomb. Calling openOptionsMenu does absolutely nothing if you do not have the ActionBar visible.

Any thoughts on how to deal with this?

  • I suppose I could always go back to using TargetSDK < 11 (thereby forcing the ActionBar to appear on tablets), but as far as I can see this is merely pushing the problem into the future, which I would prefer not to do.

  • Drop the Options Menu entirely, and go over to only using Context Menus? [Clarification: By this I mean that instead of opening an options menu - I only use context menus since - at least for now - these work on all devices].

Interested in hearing what others who have had similar issues with the whole Options Menu/ActionBar mess decided to do.

Let me share another scenario where Menu Button becomes critical even though it is not a game.

I have app implement its own tool bars which behave to some extent like ActionBar. Well I did that coz my app was released with 1.5 sdk. At that time there is no such concept. And to accomodate for my toolbars i hide the default title bar. But some of the actions are done through Menu functionality.

Now since in Galaxy Nexus there is no Menu button if you are not using ActionBar and that is hurting me bcoz my app still supports 1.5.

Well there are various work arounds, but none is easy.

That said, the only work around I come up with is to give user all options on my toolbar, so there is no need for Menu at all. I can do this bcoz i only have two actions which are not part of the toolbar.

In your situation, context menu on a button is not a bad soln in a game as game will have only one context in which it is running as compared to having context menu on list items where every item is a different context.

BTW if openOptionsMenu works on ICS and you can ditch HoneyComb after a while (even now the userbase is too low) then try giving both menus based on the version.

EDIT: Well there is another way also to get the MENU s/w button in the below navigation bar. Just set the targetSdkVersion to less than 11. For more details pls read the whole soln.

SSL certificate for REST web services (used by Android)?

8 votes

I have a website with a number of RESTful web services that are used by an Android app. I want to let all requests go through HTTPS. Hence, I need an SSL certificate for my website.

Q: Do I need to buy an SSL certificate or can I use a self-signed certificate in this case? (I don't want to waste money on something I don't need.)

I can think of these approaches:

  1. Buy an SSL certificate with Extended Validation (green address bar). Probably not necessary.
  2. Buy an SSL certificate without Extended Validation. This should suffice, no?
  3. Self-sign an SSL certificate. Not sure what this implies?

If your biggest concern is not spending money http://www.startssl.com/ provides free basic SSL certificates for a year so that may be worth looking into. I do not know off-hand which CAs are trusted by default in Android so it may turn out to be effectively the same as a self-signed certificate from the app's perspective.

Using a self-signed certificate would require finding a way to make sure the Android app expected that self-signed certificate and trusted not only your initial certificate but any replacement certificates in the future. I suspect this is more trouble than it is worth although I do not know much about Android development or the app in question so I may be overestimating the difficulty involved.

An EV certificate does provide a stronger guarantee to the client that the service is actually your service and owned by you but it does incur additional costs. Choosing an EV versus DV certificate becomes more of a risk/reward judgement call. Annecdotally, I typically only see EV certificates on financial sites and others where you would typically expect to find a high bar for security.

What is the purpose of the "developer payload"? What can it be used for?

7 votes

The Android docs say that its meant for "supplemental information about an order" but at the same time it also says not to use this to send "actual data or content".

So what is the purpose of this "developer payload"? Why does this feature exist? Can you describe a real-world practical example of how I can use it in my own In-app Billing implementation?

As aromero mentioned the developer payload field is limited in size. This is why the docs recommend not to use this key to send data or content.

What you do instead is save the content to a database somewhere (e.g. on the user's device or your own server), and then put the record's index in the developer payload field. When you receive it back via the PURCHASE_STATE_CHANGED broadcast intent, you can associate it with the data in your database.

Note that the developer payload is not sent by the Market when using any of the test android item ids. You have to be using real in app purchase items.

Also, according to this (I have not verified this yet), you will not be receiving the developerPayload in DEBUG MODE. You need to sign your application to RELEASE MODE to receive developerPayload.

Lastly, as you commented below, the returned JSONObject (in response to GetPurchaseInformation) already includes orderId, productId, purchaseTime and more. So "developer payload" should actually be used for anything but to identify the purchase... i.e. the answer is the opposite of what has been suggested below. What you can use "developer payload" is to add some information not in the JSONObject, like purchaser's additional details (e.g. GPS location if enabled, device brand & model, etc.).

Securing communication [Authenticity, Privacy & Integrity] with mobile app?

6 votes

An Android/Iphone app will be accessing application data from the server. [Django-Python]

How can I secure the communication with the mobile app ?

Expectation : Secure enough for sensitive information like passwords, there shall be no direct way of decryption except brute-forcing.

My requirements :

  • Authentication [Only the app is authorized]
  • Integrity [Messages should not be modified in between]
  • Privacy [Communication should not be readable if sniffed]

My effort:

  • SSL authenticates only the Server, not the client.
  • I can-not use a symmetric encryption [Provides only Privacy]
  • Digital signature is not possible [Lacks Privacy]
  • PGP full-fills all 3 requirements.

Problem :

  • PGP requires to store keys on client app.
  • There seems to be no assuring way of securing keys on client app.
  • If the key is out, then PGP or Symmetric encryption are equally vulnerable.
  • Reverse-Engineering PGP keys or symmetic keys is equally hard.
  • In that case PGP is a non-sense burden on the mobile processor.
  • OAuth is again useless, since it also have a client key.

So, how can/should I move forward on this ? How does the industry deals with this ?

Should I implement casual approach :

  • Use simple SSL and cross my fingers ?, since authentication is not possible if the keys are stolen? (Only server authentication is possible with this)

You're working on bad information. SSL can absolutely authenticate the client, it's just not something that is done for the bulk of SSL as the protocol is (or, atleast was) typically used to protect e-commerce sites where authentication of the server was important but doing so with the client was not important and/or not feasible. What you want to do is employ mutually-authenticated SSL, so that your server will only accept incoming connections from your app and your app will only communicate with your server.

Here's the high-level approach. Create a self-signed server SSL certificate and deploy on your web server. If you're using Android, you can use the keytool included with the Android SDK for this purpose; if you're using another app platform like iOS, similar tools exist for them as well. Then create a self-signed client and deploy that within your application in a custom keystore included in your application as a resource (keytool will generate this as well). Configure the server to require client-side SSL authentication and to only accept the client certificate you generated. Configure the client to use that client-side certificate to identify itself and only accept the one server-side certificate you installed on your server for that part of it.

If someone/something other than your app attempts to connect to your server, the SSL connection will not be created, as the server will reject incoming SSL connections that do not present the client certificate that you have included in your app.

A step-by-step for this is a much longer answer than is warranted here. I would suggest doing this in stages as there are resources on the web about how to deal with self-signed SSL certificate in both Android and iOS, both server and client side. There is also a complete walk-through in my book, Application Security for the Android Platform, published by O'Reilly.

findViewById(int) returns null on one specific button in Android 3.1 other versions its fine

6 votes

it's my first question but i'm trying to ask correctly.

As the title says only on one button and only in android 3.1 findViewById(int) returns null. Testing on Android 2.2 it works and all other buttons are found in both Android versions. It finds buttons before this specific line and afterwards.

codesnippet:

public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonInfo = (Button)findViewById(R.id.buttonInfo);//fine
buttonInfo.setOnClickListener(this);
...
Button buttonCallOpScreen = (Button)findViewById(R.id.buttonCallOpScreen);//always returns null in android 3.1
...
Button buttonTakePicture = (Button)findViewById(R.id.buttonTakePictureMain);//fine
buttonTakePicture.setOnClickListener(this);
}

main.xml-snippet:(I do know, that i should not use px but it shall work on my device only, so thats fine for this case.)

<Button 
android:id="@+id/buttonInfo" 
android:text=""
android:layout_width="332px"
android:layout_height="100px"
android:background="@drawable/btn_team" />
...
<Button
android:id="@+id/buttonCallOpScreen"
android:text=""
android:layout_width="332px"
android:layout_height="100px"
android:background="@drawable/btn_operator" />
...
<Button 
android:id="@+id/buttonTakePictureMain" 
android:text=""
android:layout_width="80px" 
android:layout_height="80px"
android:background="@drawable/btn_take_picture"
android:layout_gravity="bottom|left" />

Any help would be appreciated, thanks so far.

greetings martin


Answer:

It turned out to be a more than ugly. As there are several persons working on this project one of seemed to have changed the name in the layout-normal/main.xml. While Android-Versions before 3.1 seem to load layout/main.xml the newer ones use layout-normal/main.xml. And as it is more than understandle if the id of that button is a different findViewById(int) has to return null.

Sry for bothering you with that and thanks for the comments!

As i do have less than 100reputation I can't answer my own question to close it, if anyone could post this answer i would accept it, thanks.

greetings martin

The following answer was discovered by the person who asked the question. The details are:

As there are several persons working on this project one of seemed to have changed the name in the layout-normal/main.xml. While Android-Versions before 3.1 seem to load layout/main.xml the newer ones use layout-normal/main.xml. And as it is more than understandle if the id of that button is a different findViewById(int) has to return null.

Fastest and most efficient way to pre-populate database in Android

5 votes

If you want to pre-populate a database (SQLite) in Android, this is not that easy as one might think.

So I found this tutorial which is often referenced here on Stack Overflow as well.

But I don't really like that way of pre-populating the database since you take the control from the database handler and create the files yourself. I would prefer to not touch the file system and let the database handler do everything on its own.

So what I thought one could do is create the database in the database handler's onCreate() as usual but then load a file (.sql) from /assets which contains the statements to fill in the values:

INSERT INTO testTable (name, pet) VALUES ('Mike', 'Tiger');
INSERT INTO testTable (name, pet) VALUES ('Tom', 'Cat');
...

But calling execSQL() in the handler's onCreate() doesn't really work. It seems that the /assets file must not have more than 1MB and the execSQL() only executes the first statement (Mike - Tiger).

What would you do do pre-populate the database?

I suggest the following:

  1. Wrap all of your INSERT logic into a transaction (BEGIN... COMMIT, or via the beginTransaction()... endTransaction() APIs)
  2. As already suggested, utilize the bind APIs and recycle objects.
  3. Don't create any indexes until after this bulk insert is complete.

Additionally take a look at Faster bulk inserts in sqlite3?

Advantage of schemaless data storing over data storing with schema

5 votes

I want to choose a back end web service for my app. Reading documentation of these services(Parse, Proxomo, Cocoafish, StackMob etc.) reveal that some of them offers to store data in schemaless form while other mention that schema must be specified apriori. I understand what is schema of data is and hope schemaless will be easy to use, but want to know merits and demerits of each. Any explanation will be greatly appreciated.

The biggest difference is scalability.

Data storage solutions with schema are much harder to distribute than Schema free data storage solutions. Its really easy to replicate (schema free) key-value pairs for fault-tolerance. Its really easy to distribute copies across nodes for fast read times and its easier to provide fast writes with eventual consistency. If you are managing your own database this means it will be much easier to manage schema free solutions when you need to scale to multiple servers. If you are using a service this means schema free solutions are normally cheaper and faster.

The problem with schema free comes when you need transactions and consistency across various data-sets or tables. All this has to be done in code.

So the bottom line is: If you need huge volume data with fast access cheap it has to be schema free. If on the other hand your data size and load is modest than schema based systems are better.

If you need help choosing which service to go with, A better way to decide would be to do a read/sec write/sec and expected data size analysis on your application and then choose which solution is cheaper. All of these services will presumably scale to your loads but the cost will be the deciding factor.