[Android] Deployment process, from code to your phone

You may consider yourself an expert Android programmer, and you might even have successful apps published in Google Play Store, but sometimes, IDEs are so easy and helpful, that we forget to worry about what’s happening behind the scenes. This graph extracted from http://developer.android.com/tools/publishing/preparing.html and very well explained by the guys at http://www.bignerdranch.com/, explains every step that is happening when we click on the “Run” button. After understanding it, some technicisms that we often see in the log messages (aapt, zipalign, Dx, dex, dalvik) may sound more familiar for us.

Android App deployment to phone

Advertisements

[iOS] A simple way to move your PDF documents to your iPad without iTunes: Using Google Drive

1.- Upload your PDF document to Google Drive

2.- Download Google Drive App in your iOS device, open your Google Drive Folder

3.- Open the PDF from Google Drive, click on the icon at the top-right corner, select “Open in…“. Select iBooks.

4.- Et voila, your PDF will be downloaded and included to your iBooks library.

 

I know there many more ways of doing that, but most of them are annoying:

– Dropbox is all the time coming with “buy more storage, invite people for more storage, do a handstand for more storage, buy buy BUY BUY” and it’s very annoying.

– iTunes politely invites you to “synchronise your iPhone/iPad”, deleting all the content that Apple might not like, to have their users under control (mmh nice try Apple).

So with that simple steps, you can have your PDF for reading without too many annoying obstacles. We are storing on Google Drive, so make sure your PDF does not contain the words “murder” or “president”, or else the FBI will be knocking your door in a couple of hours 😉

Enjoy!

 

[Android] Usual problem with asnychronous requests: Updating a no-longer-existing Fragment

If you are using asynchronous requests (e.g. AsyncTasks, Services+BroadcastReceivers, android-volley, android-async-http or any other flavour), this scenario may sound familiar to you:

1.- in the Activity’s onCreate() or onResume() method, an asynchronous HTTP request is sent
2.- User quickly destroys the Activity (for example, rotating the phone)
3.- Response to the request made in step 1 arrives, the onResponse/onHandleIntent callback is fired, but the Activity/Fragment is no longer existing, because you have destroyed it in step 2. so BOOM!!! App crashes, giving your users this undesirable “Has stopped unexpectedly” message, and generating such a bad experience with your app.

Typical error message:

java.lang.IllegalStateException Fragment MyFragment not attached to Activity

The simplest and smartest solution for that is using Fragment’s isAdded() method:

if(isAdded()){
mGridView.setVisibility(GridView.INVISIBLE);
// … any other update you need to do in the views
}

So if you reproduce the steps above, isAdded() will return false and application won’t crash.

[Android] Managing Preference screens smoothly

If you are planning to implement a PreferenceActivity (preference screen) in your App, i highly recommend you to have a look at this example App made by CommonsWare. Have a look at the EditPreference class and how it handles headers, then the different kind of SharedPreferences (checkboxes, lists, inputs, etc), without needing to elevate complexity introducing additional Fragment classes (Fragments are private classes inside).

Quite an excellent work 🙂

Have a nice coding day!

[iOS SDK] How to test In-App purchases in your iOS device.

One difficult thing to implement in iOS SDK is an App offering In-App Purchases (from now on, IAPs). There are plenty of tasks to be done in iTunes Connect (Tax, Banking and Contracts, Manage Test Users, Manage Apps, Create App IDs, certificates, provisioning profiles, …), then tasks to be done in Xcode, and also a few more in the iOS device (look well, I said iOS device! and not SIMULATOR!).

The first thing you have to know is that In-App Purchases cannot be tested on the iOS Simulator. If you were trying to do that, or were planning to try, spend your time in something better.

But even in the iOS device, it is not trivial to find the way to test if our IAP implementation is working fine. Here are the steps for doing it. Following them carefully will for sure save you time and headaches 🙂

Prerequisites:

  • iOS App created in iTunes connect, all fields filled and screenshots uploaded. Must have “Ready to upload binary” status.
  • At least one in app purchase created for the iOS App, with its SKU and Bundle ID. I suggest you this tutorial for this point and the previous one.
  • An email account that has no AppleID associated. Immediate access to its inbox.
  • An Xcode project with IAPs implemented. I suggest you this tutorial

Steps:

1.- In iTunes connect, go to Manage Users and create a Test User with the email account mentioned previously. Fill in the rest of the fields (name, secret questions, date of birth, …). Specify a password and take note of it, we’ll need it later.

2.- Get into the mentioned email’s inbox. There should be a mail from Apple with an activation link. Click it to activate the AppleID, note that the email from Apple could be on the Spam folder.

3.- Once the user is created, in your iPhone/iPad and go to Settings > iTunes Store and App Store > Apple ID (on top). Tap on it and select Disconnect in order to logout your AppleID from the iOS device.

4.- Run your iOS App, navigate to your purchase menu, and click on the “Buy” or “Purchase” button. It will ask you for your AppleID, select Use an existing Apple ID and fill in the email and password of the Test User activated in steps 1/2. A message asking you to purchase the item in [Environment: sandbox] will appear. You can buy the item or cancel the transaction and test what happens on each case. After the first purchase, you can try to uninstall the App, reinstall, and purchase the item again to see if your restoration works correctly.  That’s all

Steps 3 and 4 are specially important because this is the only way to make the IAP test work. If you try, for instance, to log in the iPad with the AppleID and password of the Test User, it will come with “This AppleID is not activated in the App Store” and ask you for data / credit card. Also, if you try the step 4 with another Apple ID logged in (not the Test User), it will return a “Can’t connect to iTunes Store” message and IAP won’t work.

 

Hope it helps! Let me know any issues 🙂

[iOS SDK] Useful simulator shortcuts and basic operations

After a while developing iOS Apps, i’ve discovered some frequently used shortcuts that make your life easier:

In iOS Simulator:

Alt+shift: double tap (two-finger tap), for scrolling etc.

Ctrl+Alt: Pinch (zoom-in / zoom-out).

Cmd+Shift+H: Device’s Home button press

Cmd+1, Cmd+2, Cmd+3: Rescale simulator to support different screen sizes

In Xcode:

Cmd+Alt+Shift+Left: Collapse all methods in file

Cmd+Alt+Left: Collapse current code block (Cmd+Alt+Right to expand)

Cmd+7: Shows all breakpoints (Cmd+A selects them all, backspace deletes)

some simple routinary Xcode tasks:

Create segue from an UIButton to another ViewController quickly using Storyboards:

1.- [Storyboard] Place an UIButton inside the current ViewController

2.- [Code] Create the IBOutlet in the .h file, implement it in the .m file

3.- [Storyboard] Ctrl+drag from UIButton to UIVIewController.

Create outlet inside ViewController (UILabel, UIButton, UITextView…)

1.- [Code] Create the property for the outlet in the .h file

Example: @property (weak, nonatomic) IBOutlet UIImageView *img;

2.- [SB] Place the UILabel, UIButton, etc. inside the ViewController (resize it, set its title, etc)

3.- [SB] Ctrl+drag from ViewController (yellow square on the bottom) to the UILabel, UIButton, … , select the attribute defined in step 1.

Create a progress bar (slightly different than the rest of the components)

1.- Place the UIProgressView inside the ViewController

2.- Create the @property in the .h file

3.- ctrl+drag from UIProgressView to an empty zone of the ViewController. Select the attribute specified in step 2

Choose if deploying App to iPhone/iPad or to iOS Simulator:

Select Product > Destination

[iOS SDK] How to integrate Mapbox into your Xcode project, for dummies.

As an iOS dummy i was, i downloaded the mapbox basic tutorial, built & ran it, and it worked perfectly. Now i was wondering how to integrate this example in an Xcode project that i start from zero.

After some research i discovered the way of doing it, and i made myself this little guide:

1.- In your new Xcode project, click on the main target, scroll to the bottom and you’ll find “Linked frameworks and libraries”. Click on the [+] button

Captura de pantalla 2014-08-06 a la(s) 17.09.18 

2.- Now click on Add other, and locate the “Mapbox.framework” file. A copy of it is located inside “mapbox-example-ios” folder.

3.- repeat steps 1 and 2 but now locating and including “libsqlite3.dylib”, “CoreLocation.framework“, and “QuartzCore.framework“. Click on the [+] button, and on the search box type each name, it will appear.

4.- Create a new objC class extending UIViewController. In its .h file, include the #import <Mapbox/Mapbox.h>, and implement the “RMMapViewDelegate” delegate.

#import <Mapbox/Mapbox.h>

@interface MyOfflineMapViewController : UIViewController<RMMapViewDelegate>
@end

5.- copy the .mbtiles map file by dragging and dropping it to the project folder in xcode. IMPORTANT: Do not forget to check “copy items into destination group’s folder”, and to mark all the targets before clicking finish!

Captura de pantalla 2014-08-06 a la(s) 17.11.56

*If you don’t do this, you will get this error: reason: ‘*** -[NSURL initFileURLWithPath:]: nil string parameter’ (luckily, Google searches arrive here and anyone finding this error can fix it)

6.- in the .m file, initialize the TilesSource and the MapView as its done in the Mapbox example

- (void)viewDidLoad
{
[super viewDidLoad];    
RMMBTilesSource *offlineSource = [[RMMBTilesSource alloc] initWithTileSetResource:@“mymbtilesmap" ofType:@"mbtiles"];
RMMapView *mapView = [[RMMapView alloc] initWithFrame:self.view.bounds andTilesource:offlineSource];
mapView.zoom = 2;
mapView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth
mapView.adjustTilesForRetinaDisplay = YES; // these tiles aren't designed specifically for retina, so make them legible
[self.view addSubview:mapView];
mapView.delegate  = self;
}

7.- Build and run your app, navigate to the offline map ViewController. Your map should be visible. Let me know any errors / issues in these instructions.