Tech Tips

quicktip: Working with strings.xml in Android and little bit about @

Very simple so straight to the point.

BAD:

In your xmls
- <Button android:id="@+id/buy_button" android:text="Buy Me" />

In your java code
- myButton.setText("Second Button");

GOOD:

Define your strings in strings.xml (You can name it anything) and place it in ‘res/values’ folder


<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="buy_button">Buy</string>
</resources>

and then


- <Button android:id="@+id/buy_button" android:text="@string/buy_button" />
- myButton.setText(this.getString(R.string.buy_button));

Syntax for using a ‘resource’ in a xml or code is :
package.R.resource_type.resource_name
and
@[package:]resource_type/resource_name

NOTE: package here does not mean ‘java package’ but package == application, so if you are accessing a resource which is defined in your own app you can skip it. Thats why we use @strings/name or directly R.strings.name. Similarly to use resources defined by android we will use @android:string/name or android.R.string.name

For converting R.string.id to String you can either use getString(int) or getString(int, Object…) for adding dynamic values.


quicktip: How to convert a view to an image (android)

This is a quick tip to convert or draw your view on a canvas so that you can either show it as preview or use it for any drag – drop kind of operation. Very simple and self explanatory so just posting the code


View viewToBeConverted;

Bitmap viewBitmap = Bitmap.createBitmap(viewToBeConverted.getWidth(), viewToBeConverted.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(viewBitmap);

viewToBeConverted.draw(canvas);

Thats it, now you can use ‘viewBitmap’ as a normal image. You can change a few parameters to create different kinds of image, for eg when you drag your app icon on bring it on the trash can to drop it becomes red etc


How we fixed the UTF-8 supported PDF generation Issue

PDF generation was an old request by one of our client. Our team struggled a lot to solve this.
The root problem was font. We were in need of such font which can support UTF-8 characters. But none of the PHP libraries were having such support by default. Finally we selected TCPDF as the PDF generation library because it has Unicode supports and able to generate UTF-8 PDF in the presence of suitable font.

Here are the steps by which we solved this issue.

1. Searched the font supported by UTF-8 encoding and selected “osaka.unicode.ttf” as it was best matching to our requirement. Copied it into the TCPDF’s utils folder.
2. Converted it to the font’s metrics file.
- Changed the font file name to lower case.
- Used a PHP script “makeallttffonts.php” to convert the ttf file to font’s metrics file. This script comes by default with TCPDF.
- Copied generated font map files (only osaka.unicode.ctg.z, osaka.unicode.z, osaka.unicode.php)to the font’s directory.
3. Used the font name during PDF generation.


Android Push Notification

Push Notification:

Push Notification allows an application to listen for messages being ‘pushed’ to it from the server.
Through Push Notification, our apps can provide uses even when they aren’t running.

Different techniques that could be used for push notifications in android:

1)  Polling:  In this technique device is polling the server on a regular basis to see if there is anything there.

untitled.bmp

Polling that heavily just to check for notification is not a good idea,that would hurt battery life pretty badly after not too long.

2)  Creating a service: In this technique service create a persistent connection to your server.
This will also drain the phone’s battery and it will create problem on server side also if you had more users

3)  SMS: In this method clients gets notified by SMS.

untitled2.bmp

This technique is better as compare to other techniques because:

1) Transfer content as soon as available
2) Save device battery
3) Reduce data traffic for user

Way to implement push via SMS:

1) Your application should add permission in manifest :
Permission:  <uses-permission android:name=”android.permission.RECEIVE_SMS” />
2) and Registers a BroadcastReceiver, either in the manifest XML or in Java, and will get control when the events occur.
<receiver android:name=”.ReceiverClass”>
<intent-filter>
<action android:name=”android.provider.Telephony.SMS_RECEIVED” />
</intent-filter>
</receiver>
3) SMS Header may contain “app port” field that is dedicated range of free usable port numbers.Port handling not yet supported in Android 1.6.
4) You’d have to parse the PDU and get the port from there manually, you can listen to all SMS messages, parse the PDU of each incoming message and see if the destination port
matches the one that you are expecting. But so can other apps.so there’s no way to ensure that just one specific app gets to know about an incoming SMS to a specific port.
5) After matching ports appliaction can handle notification with the help of notification manager.
The problem with this method is that Android currently has no way to cancel the notification that is sent by the messaging app.So for every notification your app gets, the OS will also show a text message.


How to set up Mysql Master-Slave Replication

Replication consists of following 3 parts….

  • The master records changes to its data in its binary log (Binary Log Events).
  • The slave copies the master’s binary log events to its relay log.
  • The slave replays the events in the relay log, applying the changes to its own
    data using Slave Thread.

The basic steps to set up replication are…

  • Set up replication accounts on master server.
  • Configure the master and slave.
  • Instruct the slave to connect to and replicate from the master.

Here are few assumptions….

Master IP Address: 192.168.1.215
Slave IP Address:
  192.168.1.203
Replication User:
replication
User Password: slave

The I/O Slave Thread (it runs on Slave Server) makes a TCP/IP connection to the master. Thats why we need to create an user account on Master Server with proper privileges.

Now run the following query on Master to create a Slave account….
mysql>  GRANT REPLICATION SLAVE ON *.* TO ‘replication‘@’192.168.1.203′ IDENTIFIED BY ’slave’;

Now edit my.cnf file on Master accordingly.

[mysqld]
server-id                       = 1
log-bin                          = mysql-bin
log-bin-index                = mysql-log-bin.index
relay-log                       = mysql-relay-bin
relay-log-index             = mysql-relay-bin.index
expire_logs_days         = 10
max_binlog_size          = 100M
binlog_do_db               = [Database Name to be Replicated]
binlog_ignore_db         = [Database Name not to be Replicated]
#binlog_ignore_db       = [Database Name not to be Replicated] (for more than one data base which is not supposed to be replicated)
datadir                          = /var/lib/mysql
tmpdir                           = /tmp

Now restart Master mysql server and run the following query…

mysql>  SHOW MASTER STATUS;

screenshot-1.png

Now edit my.cnf file on Slave accordingly…..

[mysqld]

server_id                = 2
master_host            = 192.168.1.215
master_user            = replication
master_password   = slave
master_port            = 3306
relay_log                = mysql-relay-bin
relay-log-index       = mysql-relay-bin.index

We can set the value for master_host, master_user and master_password using mysql query. So it is better to avoid setting those values  directly from configuration file.

If master is having data already, insert the data from master server to slave server database or each of the databases.
Copy master database back up inside slave server and run  the following command on slave….

mysql -u[username] -p[password] [database name] < directory_path/[database.sql]

Now Restart Mysql Slave server and  run following query to synchronize master and slave….

mysql> CHANGE MASTER TO MASTER_HOST=’192.168.1.215′, MASTER_USER=’replication’, MASTER_PASSWORD=’slave’, MASTER_LOG_FILE=’mysql-bin.000004′, MASTER_LOG_POS=570;

Note: MASTER_LOG_FILE and MASTER_LOG_POS values have been taken from the result of SHOW MASTER STATUS

If a Slave is already running on your Slave Server,  Mysql Server will throw a error like…
ERROR 1198 (HY000): This operation cannot be performed with a running slave; run STOP SLAVE first

So run..
mysql> STOP SLAVE;
And  run the query for CHANGING MASTER again.

If it shows an error like..
ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MySQL error log

Run
mysql> RESET SLAVE;

And  run the query for CHANGING MASTER again.

Finally start slave on slave server using..

mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G

screenshot.png

Congrats! Mysql Master-Slave Replication has been set up :)

Also we will be able to see the Replication Threads in the process list on both the Master and the Slave.

So simply run…

mysql> SHOW PROCESSLIST.


Random differences between CodeIgniter and symfony

1) CodeIgniter is sleek, easy to learn compared to symfony.

2) CodeIgniter project set up time is very less compared to symfony.

3) CodeIgniter works well for something quick and small, symfony hits when it comes for complicated projects.

4) As CodeIgniter does not accept arguments via the command line, you can not call a specific controller or function, a work around should be adopted but it’s not the case with symfony as it provides a concept called task.

5) CodeIgniter does not have any code generators like symfony which completely rocks symfony.

6) Working with fixtures makes life easier in symfony during development phasem, this is missing in codeIgniter again a run  around should be done.

7) Symfony allows to view the queries fired through development environment but codeIgniter has no such option.

1 Comment more...

Android NDK – an introduction (How to work with NDK)

What is the Android NDK?

The Android NDK is a companion tool used only in conjunction with Android SDK which allows application developers to build performance-critical portions of their apps by use of native (C/C++) code.

This provide benefits in form of reuse of existing code and increased speed.

Contents of NDK:

  • A set of tools and build files for generating native code libraries from C and C++ sources.
  • A way to embed the corresponding native libraries into application package files (.apks) that can be deployed on Android devices.
  • A set of native system headers and libraries supported starting from Android 1.5 .
  • Documentation, samples, and tutorials.

Download NDK from http://developer.android.com/sdk/ndk/1.6_r1/index.html and uncompress it.Now run the script in <NDK>/build/host-setup.sh.This creates <NDK>/out/host/config.mk which configure NDK for system.

How to write an application using NDK?

Follow underneath steps to create our own application using NDK and make it running on emulator.

Write an Android Activity

You need to include following lines of extra code in our java file.

  • Call native method inside on create method.
  • Declare native method outside oncreate method.
  • Call to “System.loadLibrary” method inside a static initializer block to load our shared library object.

package com.example.FileLoaderActivity;

public class FileLoaderActivity extends Activity {

private static String TAG = “FileLoaderActivity”;

// The name of a test file to write

private static String FILENAME = “hello”;

// The full path to the test file

private static String PATH = “/data/data/com.example.FileLoaderActivity/” + FILENAME;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

……………

// Call the native method to read the file just written

byte[] bytes = loadFile(PATH);

…………..

}

public native byte[] loadFile(String fileName); static {

System.loadLibrary(“fileloader”);

}

}

Generating C/C++ header files For generating C/C++ header file for our shared library:

  • Build project which generates Java.class files under <project_home>/bin
  • Use javah tool to generate a C/C++ header file.

Issue the following command at the top of <project_home>, my command looks like:

javah -o fileloader.h -classpath bin com.example.FileLoaderActivity.FileLoaderActivity

The above command will generate a file called fileloader.h .

Creating our Shared Library

Create two folders which will contain source code and make files:

  • mkdir -p ~/workspace/<project_home>/jni foldercontain the source code for our shared library.
  • mkdir -p $NDK_HOME/apps/fileloader folder- “project definition” folder for our shared library

Now copy header file ‘hellondk.h’ from Eclipse project folder to ~/workspace/<project_home>/jni/

For building our NDK project, we need to create two Makefiles which will specify how and from where to pick source code and library file.

  • Android.mk
  • Application.mk

~/workspace/<project_home>/jni/Android.mk

Android.mk file describes source file to build system and its contents are :

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := fileloader

LOCAL_SRC_FILES := fileloader.c

LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog

include $(BUILD_SHARED_LIBRARY)

$NDK_HOME/apps/fileloader/Application.mk

Application.mk file describes modules that are needed by your application and it looks like:

APP_PROJECT_PATH := ~/workspace/FileLoaderActivity

APP_MODULES := fileloader

Creating Shared Library Source

Now create C source file for shared library which defines JNI method called by Java file.Signature of this Jni method should match with fileloader.h file generated by eclipse build system.

~/workspace/FileLoaderActivity/jni/fileloader.c

jbyteArray Java_com_example_FileLoaderActivity_FileLoaderActivity_loadFile

(JNIEnv* env, jobject thiz, jstring filename)

{

……………………..

}

Compiling our Shared Library

Change current working directory to $NDK_HOME and run command “make APP=fileloader”.You can find your shared library into folder $NDK_HOME/out/apps/fileloader/ directory.You can now run our FileLoaderActivity project from within Eclipse. Dont forget to push file “hello” mentioned in java code before running project.Here’s a screenshot of what you should see in the emulator.

device.png


How we fixed production push notifications not working while sandbox works

We have faced the issue of push notifications working seamlessly over sandbox but never work on production. This has happened more than once.

I still have not investigated the root cause but the following fixes it.

We did not do anything extra or change any code or project build configuration. Here is what we did:

  1. Restored our iPhone/iPod Touch devices by erasing everything and reinstalling the OS. Did not sync the device or restore old data to avoid putting in the provisioning profiles again.
  2. Deleted all certificates and private keys from keychain on the mac (all including the Apple provider certificates)
  3. Removed all provisioning profiles from xcode.
  4. From the developer portal, we deleted the adhoc and dev provisioning profiles
  5. From the developer portal, we revoked the push SSL certificates for both dev and production versions
  6. Then we regenerated the push SSL certificates, both production and dev. Note that we did not download them from the wizard itself at this time.
  7. We then waited for a few minutes (5-10 mins) and then generated the provisioning profile. Not downloaded yet.
  8. We again waited a few minutes (5-10 mins) and then downloaded the certificates (sandbox and production) and the profiles (dev and adhoc)
  9. We then generated the single PEM file from the certificates and the key only for the production version. We did not even install the sandbox version certificates in our keychain.
  10. Then installed the adhoc provisioning profile in xcode and the device
  11. Started the application and tested a push notification
  12. It worked

They key difference is that we generate and download the dev profiles and sandbox certificates but do not use them at all. We only use the production certificates and the adhoc profile. That seems to always work.


iPhone OS backward compatibility, Target and Deployment SDKs and AdWhirl integration

Since many iPhone and iPod Touch users have not upgraded to the iPhone OS 3.0, it makes a lot of sense to enable backward compatibility on applications. But if you want to leverage the latest 3.0 features, you would have to put some extra effort to ensure full backward compatibility.

And if you are also integrating 3rd party libraries (analytics, ad networks etc.), you would have to ensure those also are backward compatible.

Q: How can I ensure that my application works on all iPhone OS versions from OS 2.0 to the latest 3.x version? And I do need to use some 3.0 features like push notifications or the Map Kit functions.

  1. Choose the Base SDK as iPhone Device 3.0. You can do this by right click on project name->Get Info. Then on the General tab, set the “Base SDK for All Configurations”to “iPhone Device 3.0″.
  2. Choose your deployment to be the lowest version you want to support. You can do this by right click on project name->Get Info. Then on the Biold tab, select “All Configurations” for Configuration so that this change is applied to all you configurations. Then look for the “iPhone OS Deployment Target” property under the “Deployment” section. Set that to the correct iPhone OS version. In my case I set it to “iPhone OS 2.0″.
  3. In your code wherever you use any APIs available only in versions later than your deployment target, use them conditionally after checking if they are available. This can be done for both classes and selectors.

Apple’s documentation describes this in further detail. Here is an image from the documentation that describes how the compatibility works based on the configuration:

When using 3rd party APIs and linking to dylib libraries, there might be further problems if the versions are not compatible. When trying ot integrate AdWhirl, we got an error:

Dyld Error Message:
  Library not loaded: /usr/lib/libxml2.2.dylib
  Referenced from: ......
  Reason: Incompatible library version: xxxxx requires version 10.0.0 or later, but libxml2.2.dylib provides version 9.0.0

This happens because iPhone OS version 2.x  and 3.xuse different versions of the library. The simplest way to fix this is to make the linking for the library weak. This can be done by right click on your application under “Targets” and select Get Info. Then on the General tab, under the linked libraries, locate this library and change the linking type from “Required” to “Weak”


Writing good code – Design patterns group formed

This is how we at TechJini define good code
- Code that fulfills customer requirement. This is the most important of all, no matter how you have coded, what process you have followed if it doesn’t do what is expected of it, its useless. Ofcourse has to be bug free.
- Easily maintainable code. Do not write thinking that you are responsible only for version 1.0. Think ahead, code should be very easy to maintain. Easy maintenance include – easy for new team members to understand, easy to test, easy to change/add features, well documented etc
- Reusable. Code which can be transformed into components and reused.
- Thoroughly tested, test cases should have full (maximum possible) code coverage.
- Future and change ready.

There are several things we can do to ensure that we write ‘good code’, one of the way is to start with good design. Understanding and having ability to correctly utilize OOP concepts and design patterns. To ensure that everyone in our company is a master we have formed and started TechJini Design Patterms study group. We had our first class yesterday which covered introduction of OOP concept and healthy discussion covering real life examples trying to model real life problems. Its clear that everyone has good base and is an expert in analysing and applying OOP concepts, so we expect to have good discussions in future.

Next session is about Abstract Factory Pattern. Looking forward to it.


© Copyright 2009 TechJini Solutions Private Limited. All Rights Reserved
iDream theme by Templates Next | Powered by WordPress