Androidsx is now Perops. Visit us at perops.com

Androidsx Androidsx | android and wearable developers

 

Subscribe for market insights and new posts

 

Wearable computing and developers: Android-powered smartwatch by Google?

September 7, 2013 at 11:29 pm | android, blog | No comment

 
Wearable computing and developers: Android-powered smartwatch by Google?

Update Apr 20 2014: Google released Google Wear SDK, lots of interesting opportunities happening for wearable developers that wants to enter into the niche of developing smartwatch applications.

A few weeks ago, Samsung revealed their brand new smartwatch called Galaxy Gear. According to Bloomberg, Apple is working in a smartwatch too. And, last week Google announced they acquired the Android-powered wearable-device company WIMM Labs last year.

It definitely seems like a new market is opening up here. The outlook is exciting for developers, since it is more than likely that they will publish SDKs for developers to develop apps for this new wave of wearable devices.

Two years ago, we collaborated with WIMM Labs as part of their Innovation program: we developed a News Reader application. We adapted our AnyRSS application to this new platform.

It was quite an exciting venture. The navigation is completely different, and the screen size requires the user interface to be very optimized. Also, the battery power is very limited, and the conditions to access the network are radically different. Also, the lack of keyboard must be accounted for in the most comfortable way for the user.

Our app was reviewed in well-known tech media blogs and magazines, being one of the most exposed 3rd party apps for the WIMM One devie. Suddenly, they shut down for no apparent reason. Now we see why: Google knocked on their door.

We’re excited to see what opportunities these new wave of devices bring for developers. We may need to load the code of our News Reader again! This time we won’t integrated with Google Reader, though : )

 

How to link/add an Android library project with Gradle in Android Studio

July 29, 2013 at 1:28 am | android, blog | 22 comments

 
How to link/add an Android library project with Gradle in Android Studio

This post intends to share how to import and add your Android project from Eclipse into Android Studio and Gradle, the new build system for Android. In particular, we address the case where you use at least one Android library project.

To answer this question, we have prepared this project in GitHub that just does the bare minimum to get this setup working:

  • An Android application in the HelloWorld project.
  • An Android library in the MyLibrary project library.

Once it is done, it all looks fairly obvious. The key is to add a dependency from the application project, in the build.gradle file:

dependencies {
    compile files('libs/android-support-v4.jar')
    compile project(':MyLibrary')
}

And, in the IntelliJ Module file, HelloWorld.iml:

<orderEntry type="library" name="android-support-v4" level="application" />
<orderEntry type="library" name="MyLibrary.aar" level="project" />

In the library project, there’s not much to do: tell Gradle and Android Studio that this is an Android library, with apply plugin: ‘android-library’ and <option name=”LIBRARY_PROJECT” value=”true” />, respectively.

In our case, for Chat Toolkit, we have a few libraries, so our property files are a bit more complicated:

Chat Toolkit modules

If your dependency tree is also complex and you’re unfamiliar with Gradle, we’d strongly encourage you to experiment first with this Hello-world type project to understand the basics before you migrate your project.

Good luck!

 

Technical Debt In Android App Development

January 7, 2013 at 5:06 pm | android, blog, software quality | 11 comments

 
Technical Debt In Android App Development

Many indie developers think they can get away with introducing hacks all over the place while developing an Android application. Those shortcuts do speed up development. Probably, they’ll even take you closer to the launch day.

However, chances are that they’ll end up doing more harm than good.

The main reason is pure technical debt. Technical debt makes reference to the work that remains to be done in a project in order to consider it complete. All those hacks contribute directly to it.

As described in a a CAST report, the technical debt is like a ticking bomb: first, it doesn’t go off with a bang, it’s more a slow burn. Change starts to take longer… and operation costs start to spiral — it will not be a single cataclysmic event; it will be death by a thousand cuts.

In this list, we’ll attempt to classify the different types of technical debt, sorted by how much damage they inflict:

  • Choosing the wrong technology for your platform. Migrating to a different technology usually implies changes at many different levels, plus learning the new platform. A very costly process. This doesn’t usually apply for an Android app, tough.
  • Designing the wrong architecture. If the architecture does not fit the problem it intends to solve, extensions become more and more cumbersome, until a major rework may remain as the only alternative to scale. This is usually a huge task to tackle. This applies for big applications, where several layers communicate to each other.
  • Error-prone code. Code that is hard to understand, and thus expensive and dangerous to modify. Also, difficult to extend. It was perhaps originally done badly, or it worsened with subsequent modifications. Many of those hacks fall within this category.
  • Code that is difficult to test. If it is difficult to test, chances are that it falls in both the previous (Error-prone code) and the following (Poorly tested system) categories. Testing costs tend to go up with future changes, which just makes things worse. Remember that even if you don’t create an Android Test project, or you don’t do GUI testing, you can still write traditional unit tests for the critical modules of your application. You’ll be glad you did.
  • Poorly tested system. This leads to the classic I fixed X, but broke Y by mistake. No tests warned you about it. As a consequence, one tends to become lazy when it comes to improving the design: attempting to refactor a poorly tested system is scary. On the other hand, a well-tested code base provides you with confidence to improve things with a higher expectation of succeeding. After many releases, the time spent doing manual testing (aka click around before the release and hope everything works as it used to) will surpass the time it would have taken to write proper tests in the first place.
  • Duplicated business knowledge. if the DRY principle is applied successfully, a modification of any single element of a system does not require a change anywhere else. Often, the “rename” operation is expensive and extremely error-prone. In practical terms, your constants are defined in a single, central location, right? How about your assumptions about what extras your activities accept, or the data format you use for storing data into persistent storage?
  • Missing or poor error handling. Does your application let Force Closes happen? Or even worse, does it catch exceptions and try to go on as if nothing had happened?

  • Inefficient implementation. Isolating the bottleneck, profiling and fixing it is not an easy task. If your application is a service, do make sure you won’t drain the phone battery. You really want your applications to feel responsive in all supported devices.
  • Code that works, but nobody quite understands why. Usually somebody that left wrote it, and it’s been running untouched for a long time. Sooner or later, somebody is going to have to fix it or adapt it to whatever external change. That may be expensive in terms of time and frustration.
  • Outstanding bugs in code and unresolved static analysis warnings. It depends on the severity of them. However, many of them may have been there already for a long time, and didn’t cause any real problems yet. A cheap fix.
  • Duplicated code. This is one of the first things that comes to mind when discussing technical debt. One of the star features of static code analysis tools. But, how bad is it? In a given codebase, there may be several versions of some assertContains method. Sure, we’d be better off if they were in some commons library. But how much harm do they do, in terms of maintenance costs? I’d argue it’s not much.
  • Outdated documentation. Out-of-date documentation can lead you in the wrong direction, when it claims things that don’t hold anymore. Write little documentation, but make sure it is close to the code, and up to date.
  • Bad style: magic numbers, missing comments, wrong indentation, … Untidy code is more tedious to read. But this is trivial to fix. (By the way, fixing the formatting is fine as long as it is not done in the same changeset as a change in the actual logic.)

The point is, use your limited time in the most effective way. Fixing all warnings feels good, but, does it help that much? Did you make sure your design is scalable?

Talking about scalable designs, we pretty much killed our suite of News Reader applications because of a few bad design decisions. Long, long time ago we launched AnyRSS, a simple, widget-based RSS reader. It is the parent application for several other single-RSS readers, such as FML. They were great, the CTR in both Admob as well as Mobclix for them was really high, compared to our other applications. As you can imagine, all these applications share almost all functionality. But the architecture was just not right.

We are definitely not doing the same mistakes with Chat Toolkit and Smileys For Chat. The setup is similar: several free applications perform upselling to a paid one. Not a single line of code, not a single string, is duplicated (well, almost). Several module libraries collaborate to create these applications, and they have well-defined responsibilities and APIs. Coding new features is just so easy as doing it on top of a Hello World app, and most modules have a way of running in stand-alone mode.

There are other reasons why you want to keep a well-designed, clean, clearly documented codebase. What if you want to bring in a contractor to help you out? Will it be easy for them to get up to speed? Or is it just impossible? Can you give them one single module on which to work, or is the whole code a piece that can’t be easily decomposed in subpieces (i.e., different JARs)?

Also, are you proud of your code? Would you publish it into GitHub? Maybe at some point you want to have some of your code published while considering a job change? But, is it good enough to be out there in the open?

Some interesting articles we have checked out in order to write this post:

 

New features in Java 7

September 27, 2012 at 10:37 pm | blog, general | No comment

 
New features in Java 7

Here’s a summary of the most exciting features of the upcoming Java 7, which is of interest for the Java community and, consequently, for Android developers!

Language enhancements

Left to right type inference

This basically allows you to write Map<String, List<String>> retVal = new HashMap<>(); instead of Map<String, List<String>> retVal = new HashMap<String, List<String>>();, which is unnecessarily verbose.

It also infers the type of the return type: in a method whose signature is Map<String, List<String>> parseSomething() you can just return new HashMap<>(); and have the generics information inferred.

Using strings in switch statements

A natural extension of the switch statement. No longer do we have to map those strings to integers or enums, or write error-prone anidated if statements. It’s also a bit more efficient. For details see the Compilation section in the initial proposal.

Automatic resource management

Not much ago, we spent quite some time tracking down a bug because some DB connections were not closed. In complex infraestructures (i.e., where you use Spring, define several aspects to AspectJ, but sometimes you also program at the low level for optimization purposes), this is not always a trivial topic. Making sure you free this type of resources will no longer be necessary.

With Java 7, you can write

try (InputStream is = new FileInputStream(new File("foo.txt"))) {
    // read the file and do something with it
} catch (IOException e) {
    // handle this
}

instead of the more verbose, error-prone:

InputStream is = null;
try {
    is = FileInputStream(new File("foo.txt"));
    // read the file and do something with it
} catch (IOException e) {
    // handle this exception
} finally {
    if (is != null) {
        try {
            is.close();
        } catch (IOException ex) {
            // ignore this exception
        }
    }
}

You can thank the java.lang.AutoClosable interface, that has just one method: void close() throws Exception;.

Improvements to literals

Underscores: now you can write int billion = 1_000_000_000; instead of int billion = 1000000000; in order to make sure you don’t miscount the 0s.

Binary literals: this is an obvious extension to the literals, now you can write int yourInteger = 0b100100101; // 293 in decimal.

Improved exception handling

It’s common (and not necessarily a bad sign) to deal with different exception types in the same way. Instead of duplicating code by copy-pasting the same exception routine, now we can use the OR (\|) operator to group the exceptions:

try {
    methodThatThrowsThreeExceptions();
} catch (ExceptionOne e) {
    // deal with ExceptionOne
} catch (ExceptionTwo | ExceptionThree e) {
    // deal with ExceptionTwo and ExceptionThree, even if they belong to different hierarchies
}

Somewhat related to this is the ability to rethrow exceptions with their original types, with no wrapping, and without the need to catch them separately. The following piece of code, valid in Java 7,

private void throwExceptions() throws A, B, C {
    try {
        // some operation that's declared to throw A, B or C exceptions
    } catch (Exception e){
        LOGGER.error("Caught " + e + " and rethrowing it", e);
        throw e;
    }
}

is exactly equivalent to

private void throwExceptions() throws A, B, C {
    try {
        throwAccordingToIndex(new Random().nextInt(2));
    } catch (A e){
        LOGGER.error("Caught " + e + " and rethrowing it", e);
        throw e;
    }
    catch (B e){
        LOGGER.error("Caught " + e + " and rethrowing it", e);
        throw e;
    }
    catch (C e){
        LOGGER.error("Caught " + e + " and rethrowing it", e);
        throw e;
    }
}

You could argue that you should be using AOP here for the instrumentation of this exceptions, but that’s another topic.

New I/O API version (NIO.2)

You’ve probably had issues at some point in time with working with absolute/relative paths, especially for programs that run in different operating systems. Also, deleting/renaming files lead to issues, as it did working with symbolic links. This version aims at making these uses cases easier.

Path

The class java.nio.file.Path will probably become the most commonly used in this package. It’s a substitute of our beloved java.io.Path, but better. You can do FileSystems.getDefault().getPath("hello.txt");, or Paths.get("file.data").getParent();. It’s basically simpler to use, especially in an environment with different filesystems.

Files

This utility class provides over 50 utility methods, such as copy(), move(), newInputStream(), readAllBytes(), createSymbolicLink(), …

Watch Service API

This new API lets you listen to some system events related to files and directories, such as when a new file is created in a directory. For details, check out the javadoc of the WatchService.

Fork and Join

The fork/join framework helps you make effective use of current architectures with many cores. It is an implementation of the well known ExecutorService, that uses a work-stealing algorithm to make sure that no worker threads idle by stealing tasks from those that are busy.

It seems fairly easy to use as long as you have a good way of splitting your processing needs into smaller tasks. There is a very handy guide in this tutorial by Oracle.

Dynamism

This does not affect us directly, but it’s a nice addition for the Java Virtual Machine, to which we are seriously tied to.

More and more dynamically typed languages want to leverage the JVM, but they are limited by the fact that the JVM was conceived to be statically typed, which implies that the type information is only checked at compile time, and thus the JVM executes this strongly-typed bytecoded without caring about the type information. This is a limitation for the dynamically typed languages where the type information is unresolved until runtime. A new feature, named invokedynamic, has been introduced in java.lang.invoke, which will allow to create performant, high quality implementations of such languages easier.

 

Our progress in Android development in 2011: Part 1

April 25, 2012 at 10:01 pm | android, blog, general | 5 comments

 
Our progress in Android development in 2011: Part 1

Let us share what we did in 2011 in the Android development field. Not that it is extraordinary in any way, but it may be interesting for some folks out there working on side projects, for you to see an example of what you can get done in a year of evenings and weekends. We’ll write follow-up posts on the topics that you guys want to know more about. Let us know in the comments!

During 2011, we had over 1.6 million downloads of our applications. These new users, together with the existing ones, generated 24 million interaction sessions with our applications. We worked on six new projects, and launched four of them. Here’s an screenshot from our Flurry stats:

Flurry stats for Androidsx in 2011: 1.6 million new users, 24M sessions

Q1 2011

For our Spell Checker and Spell Checker PRO, we tried out different monetization alternatives, and also experimented with the prices. Every week or two (depending on how significant the amount of collected data was), we’d perform a single change, either in the price, or the way we link from the Free to the Pro versions, the name, etc. Then, we measure the relevant metrics (conversion rate, number of purchases, or number of new downloads, typically) to evaluate if the change was positive or not. We also implemented some user-requested features on the graphical user interface (e.g., character count, most-used actions always visible).

All this paid off, as the revenue doubled from the initial to the optimised configuration. For the free version, we’ve been consistently getting over 100 thousand new users per month. It’s quite impressive, considering how simple the application is, and how little time it takes from us now: it has run on auto-pilot for the better part of its life, almost two years now.

We collaborated with Luis Solano to launch an iPhone version for it, iSpellChecker. This version got some attention from the national media, but it didn’t gain a lot of traction.

Screenshot of iSpellChecker

Also, we did some minor enhancements on our TFLN widget, a widget based on our AnyRSS news reader that reads from the public RSS feed of the TFLN website. Our Admob and Mobclix ad campaigns were remarkably effective there, yielding pretty high eCPM (see our post on this: Admob vs Mobclix comparison). The TFLN site owners argued it was against their Terms of Service to have this application in the market, so we unpublished TFLN.

A couple of weeks before Saint Valentine’s day, we thought, would it be profitable to launch an event-specific application? For instance, a $1 application that provides a curated, categorized, collection of gift tips for Saint Valentine’s day. To answer this question, we thought we just had to go ahead and try. We decided two days is the maximum amount of time we’d put into it. Indeed, in a weekend we hacked out and published an application named Valentine Ideas. The conlusion? No, it’s not that easy. We only had 15 purchases. Well, it was fun, anyway.

Screenshot of our Saint Valentine's app

Q2 2011

Together with Juny Crespo, we started a new project, named Deals To Me. It is an Android application that provides coupons that are active near the user, filtering the results from several coupon providers. We hired Hugo Doménech to help us with the development of the client side. In this wiki space, you can find an early draft, the code of the running prototipe we built, and some more internal documentation.

Three months into the development, we decided to cancel the project. The niche of coupons had changed a lot since we first conceived the idea somewhere in mid 2010. The main reason behind this decision was, fundamentally, that we were late in the game, where many strong players were already so well positioned.

During those weeks, we had a idea based on a common use case of ours: we’re at some friend’s place, and want to show them the pictures from the trip last weekend. We thought, wouldn’t it be cool to just press a button in your phone, and then have the photos from my phone displayed in the computer in some way that’s comfortable to watch?

Two months of work after this, we published Remote Gallery 3D in the Android market, that targets this exact use case. During 2011, we had 230k downloads of the free version, and a bit over 1k purchases of the full-featured 3.95 USD Remote Gallery 3D+ version that we launched in the end of November. We were happy with the launch, and thrilled to get so many nice comments and high ratings from users, but still feel it could rank much higher on the Android market. There’s a lot of room for improvement there, especially in terms of marketing and positioning.

Remote Gallery 3D

To be continued …

This is a summary of what we got done in the first half of 2011. Within a couple of weeks, we’ll talk about the second half of the year, and share our thoughts on where we could’ve done better.

Would you want us to go into more detail in anything in particular? Let us know!

 

How a simple dialog increased the sales of our Android app by 260%

March 28, 2011 at 8:08 pm | android, blog, monetizing | 12 comments

 
How a simple dialog increased the sales of our Android app by 260%

Short version. By introducing a dialog in our free application that encouraged the user to purchase the ad-free, paid version of it, we increased sales by 260% in the first week: 20% of the users clicked on the Go PRO button and, out of those, 15% finally bought our paid application.

Long version. We launched Spell Checker back in May 2010. It has been downloaded a million times (actually 985072, but come on, it sounds so much more cool), and has 60% active installs. It is ad-supported (by Admob, but it used to be Mobclix, see our experience with them here), and it doesn’t do too bad, with a eCPM of $0.09. The paid application is Spell Checker PRO, which is the same application, but without the ads. It used to be named Spell Checker Donate, in order to be very clear about the fact that there are no extra features.

It turns we need a user to click 70 times over our ads in our free version in order to generate more revenue than the paid one. We know this after doing a couple of operations over our Admob numbers. So, it is clear, we need to increase our conversion rate. (Still, we had a glance at our Flurry analytics, 18% of our users use our app more than 4 times a week. Not bad, but 40 clicks are way too many!)

What we did is dead simple: when you’ve used the application for 3 times, you get this dialog:

Go PRO dialog in Spell Checker

Go PRO dialog in Spell Checker

In order not to bother the user too much, we’ll wait until he has used it for 5 additional times before we show a similar dialog. Then, we’ll show it 8 times later, 13, 21, … (By the way, can you guess the next number in this sequence? :) ). The text will be slightly different each time, sort of like “So, do you like it now, or still not sure?”. Also, for existing users the message is a bit different.

While we analyzed this and other alternatives, we of course wanted to based our decision on numbers. Our estimate was that 2.5% of the active users would convert:

  • 50% of the users won’t even get to see the dialog in the first month. They are not active enough. This figure comes from our Flurry stats.
  • Out of the remaining half, 5% of them (1 out of 20) will hit the “Go PRO” button and buy it. This figure comes purely out of our air.

That sucks. We have no idea how many users will decide to buy it just because we suggest they do it. But now we know!

This pie chart shows the ratio of users that chose Free, 80%, versus those that decided to go PRO, 20%:

Users that choose PRO vs Free, from our Flurry stats

Users that choose PRO vs Free

We have matched the absolute numbers here with the actual revenue in Checkout, and it turns out that only 15% of them finally performed the purchase. That means, 3% of the users bought our application just because of our dialog. 3% is 15% of those 20%, and represents the magic ratio that we guessed out of air.

As a consequence, our daily revenue has grown by 260%, comparing the first week after we implemented this to the preceding weeks.

We are aware that the daily sales will considerably shrink after the dialog has reached most of the existing user base. So, of course this 260% won’t work for a new application. But it remains true that this has been the impact on our numbers, and hopefully all this helps you in your own estimates, which is our main objective with this post. Social behavior is so unpredictable!

We are just starting out in this fascinating world, and are aware that we are not good at selling. So help us a bit: how would you suggest we increase our conversion rate?

 

Stop the spread of nulls

October 4, 2010 at 7:38 pm | blog, software quality | 3 comments

 
Stop the spread of nulls

Say we want to write an Android application that listens to everything you say, and tries to find the information that you might need before you even ask for it. For instance, you ask your friend over the phone Is there any good pizzeria near your place?, and this application will perform a query against Google Maps using your friend’s address retrieved from your phone contacts and provide you with a couple of recommendations.

To parse the user commands, after converting the speech to text, and provide the appropriate action handlers, we have these high level interfaces:

public interface Parser {
    Action findAction(String userInput);
}

public interface Action {
    void performAction();
}

There are two proposals for the implementation of the parser:

// Altenative A
class DbBasedParserA implements Parser {
    @Override
    public Action findAction(String userInput) {
        // Find the appropriate action in the DB
        return actionFound ? theAction : null;
    }
}

// Altenative B
class DbBasedParserB implements Parser {
    private static final Action DO_NOTHING = new Action() {
        @Override
        public void performAction() {
            // Do nothing
        }
    };

    @Override
    public Action findAction(String userInput) {
        // Find the appropriate action in the DB
        return actionFound ? theAction : DO_NOTHING;
    }
}

What are the consequences of this choice? Let’s see the code of the clients [1]:

// Client for alternative A
Parser parser = ParserFactory.getParser();
if (parser == null) {
    throw new IllegalStateException();
}

Action action = parser.findAction(someInput);
if (action == null) {
    // Do nothing
} else {
    action.performAction();
}
// Client for alternative B
ParserFactory
    .getParser()
    .findAction(someInput)
    .performAction();

And this is contagious. Those if (action == null) are going to keep on spreading over the different layers of the system unless some API stops it. Help save lines of code and NPEs by ensuring no nulls are passed around!

[1] There is also a ParserFactory, with two implementation alternatives that react differently when no parser is found: one returns null, while the other throws unchecked exceptions. Back to post.

 

Can’t get our money out of Mobclix [Updated]

August 21, 2010 at 9:20 pm | android, blog, monetizing | 81 comments

 
Can’t get our money out of Mobclix [Updated]

Updates

September 12, 2013: Indeed, Mobclix scammed us. They didn’t pay us for almost a whole year now. We had most of our ad impressions directed to them for quite a while, so they have definitely made good profit off of us.

August 24, 2012: They just generated and executed the pending invoices. That was a quick reaction on their side! Still, we have not managed to match the figures of the monthly invoices with those on Mobclix’s Revenue tab (it would be great to know how exactly those are calculated).

Original post

This post is related with a comparison we did between Admob and Mobclix. Look at the Admob vs Mobclix: 1st round, 2nd round and 3rd round.

Find the updates below.

Will those numbers in your Mobclix analytics page ever turn into real money? Apparently it’s not so easy. And we are not the only ones, see here and here.

In short: we started generated revenue on March 2010 and now, in August 2010 and close to 5-figure numbers, we didn’t receive a single cent.

Long version: see our discussion with Mobclix support below.

Delayed payment

This is the e-mail that we sent on August 12 to Mobclix support:

During March, our first month with Mobclix, we generated $268.09 with our applications:

FML (803e8557-b71d-4937-b23a-8802ab22b125): $35.97
MLIA (cdf3868e-16b2-4611-ae83-4c6736400c50): $86.85
TFLN (cbc66b89-e88a-4e5e-8eb1-f3dbd36faf84): $145.27

Our questions are:
1) Why did we not receive any payment yet?
2) Why does the Invoice for June 2010 says $69.72? (Instead of $268.09)
3) Why didn’t we receive any payment yet? (We forgot this question in the original message)
These questions equally apply for the following month, April (whose invoice was generated during July)

The answer was just a document with the invoice for June (March’s revenue), splitting the contribution from every ad company. To this, we replied explaining what exactly were the mismatches between the figures in our Mobclix analytics and those in the invoice. In short, it should be 4 times bigger.

The answer was:

Mobclix will make payouts when we receive payments from ad networks. So while you may not be paid for a certain network in a month, we are working on collecting the payment and will remit it in your next invoice.

Irregularity in Revenue reporting

This is a different issue, and pretty worrying too. This was our ticket to Mobclix, on August 12:

In the Revenue tab for our applications, we noticed that, for 21-27 July, the generated revenue figures dropped a posteriori, after those days had passed. We can’’t find any reason or official explanation.

More specifically, here you have a table with the comparison of the figures that we observed before and after July 31:

DateBeforeAfter
27 July62.40$39.53$
26 July66.10$34.70$
25 July73.32$34.28$
24 July78.62$37.70$
23 July73.18$36.93$
24 July78.05$27.53$
23 July61.12$32.44$

We never got an answer.

What’s funny is that, if we hadn’t seen this, we would never have noticed. Maybe you think you made 100 dollars per day last month, but it has now magically to 40. No kidding.

Next steps

We still have hope that Mobclix will react, and understand how serious these issues are. We’ll keep you posted.

 

« Older Entries       

Categories:

Recent posts:

Search:

Subscribe