Monday, April 21, 2014

Google Cloud Messaging(GCM) for Android. (Part 2/2)

6. Implement GCM receiver code.(Client)
<< Broadcast Receiver class>>

public class GCMBroadcastReceiver extends WakefulBroadcastReceiver{
public static final String Key_Type = "Type";
public static final String Key_Command = "CMD";
public static final String Key_Msg = "MSG";

@Override
public void onReceive(Context context, Intent intent) {
    Log.i("GCMBroadcastReceiver.onReceive","new message is received.");


    Bundle extras = intent.getExtras();
    String action = intent.getAction();
    if(extras != null){
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
        String messageType = gcm.getMessageType(intent);
        // read data from gcm

        String type = intent.getStringExtra(Key_Type);
        String command = intent.getStringExtra(Key_Command);
        String msg = intent.getStringExtra(Key_Msg);

        // TODO you can add some specific code to do....
        // You can start new service to do some works.
        // startWakefulService(context, (intent.setComponent(comp)));
        // see the artical in google developer's guide http://developer.android.com/google/gcm/client.html#sample-receive

    }
}
}


7. Setup in AndroidManifast.xml file.(Client)
The instuction under ... http://developer.android.com/google/gcm/client.html#manifest

<manifest package="com.example.gcm" ...>
    <uses-permission android:name="android.permission.INTERNET" />

    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- I didn't add this permission -->
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <permission android:name="com.example.gcm.permission.C2D_MESSAGE"

android:protectionLevel="signature" />

    <uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />


<application ...>
            <receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
                <intent-filter>
                    <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                    <category android:name="com.example.gcm" />
                </intent-filter>
            </receiver>
            <service android:name=".GcmIntentService" /> <!-- if you created service to handle gcm messages you should add this service-->
</application>


8. Implement GCM message sender.(Server)
  • This is the PHP function to send gcm message to GCM connecton server.
  • You can also send gcm message to GCM connection server from you android app.
  • As you may not need it if you have a server to send the message, I will not add the codes. :-)
  • I used Curl... and you can use the lib with comment off this extesion in php.ini, if you installed latest WAMP server.
  • extension=php_curl.dll

function sendGCMMessage_($data, $registrationIDs)
{   $apiKey = 'GsfgaSFc13-2reIDSD4qK_3_dfghspVWDSxEAA'; // this is the brower key you generated in 3. Creating a Google API project and obtaining an API Key.

    $senderId = "153023456724"; // this is the project code you generated in 3. Creating a Google API project and obtaining an API Key.

    $url = 'https://android.googleapis.com/gcm/send';

 

   $fields = array(

   'delay_while_idle' => False, // If you want to receive message when the phone is idle, you have to set this 'False'. You can set this 'True' to save the battery.
   'time_to_live' => 108,
   'collapse_key' => 'score_update',
   'registration_ids' => $registrationIDs,
   'data' => $data,

   );

   $headers = array(

   'Authorization: key=' . $apiKey,
   'Sender: id=' . $senderId,
   'Content-Type: application/json'

   );

   // Open connection
   $ch = curl_init();
   // Set the URL, number of POST vars, POST data

   curl_setopt( $ch, CURLOPT_URL, $url);

   curl_setopt( $ch, CURLOPT_POST, true);

   curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers);

   curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);

   curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

   curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode( $fields));

   $result = curl_exec($ch);

   return $result;

}
  • how to call the function?? It is quite easy. 

$registrationIDs = array("APA91bEr6sdfjJzIsdfO76YsdfsvQ5NGago9JvRYod0v-n...", "APA91bEr6zWLWizsdfMO76YVRdfsfQ5NGagdfYod0vdsf...");
// The registeration id you obtained in 5. Implement GCM register code.(Client). You can add multiful registeration ids.

$data = array("Type" => "My Type", "CMD" => 'My Command', "MSG" => "My Message" );
// You should add the same key value pairs just the same as you will receive in you client app you implemented in 6. Implement GCM receiver code.(Client).
$result = sendGCMMessage_($data, $registrationIDs);
 

Sunday, April 20, 2014

Google Cloud Messaging(GCM) for Android. (Part 1/2)

1. What is GCM??

You can implement push service in you app with GCM and can find more information from this page.
This logo image is free to use.
http://developer.android.com/google/gcm/index.html

Under my experience, push messages cannot be delivered well when  user turn on wifi connection. So, you should implent pull service such as alarm notification together or develop your own push service.

The gcm message can be done under below messaging processes.

a. Register for GCM(Client)
This step only occurs on time for each client. In this step, client android app will obtain registration id from GCM connection server.
You can send the reg id to server to let server can send message to client with the key.

b. Send message to GCM connection server.(Server)
You have to implement a program to send message to GCM.
You will use the reg id of step 1.
I'll choose HTTP JSON method for this post.

c. GCM connection server tries to send message to client app.

d. Receive GCM message.(Client)
You have to implement WakefulBroadcastReceiver in your app.

2. Steps for implementation.
The step is quite simple.
  • Creating a Google API project and obtaining an API Key.
  • Set Up Google Play Services for Android.(Client)
  • Implement GCM register code.(Client)
  • Implement GCM receiver code.(Client)
  • Implement GCM message sender.(Server)
3. Creating a Google API project and obtaining an API Key.
  • go to google cloud console(https://cloud.google.com/console).
  • Create project if you don't have on yet. Copy project code to use later.
  • go to APIs & auth>Credentials and click 'Create New Key' button under Public API access.
  • In the Create a new key dialog, click Browser key.
  • When click 'create' button you can have a new browser key. Copy it to further use.
4. Set Up Google Play Services for Android.(Client)

Please see How to use Android Google Maps(API Ver2) in older Android version such as 2.3.(Part 1/2)  for this topic.
 
5. Implement GCM register code.(Client)
Your PROJECTCODE - the google API project code you created in 3. Creating a Google API project and obtaining an API Key.

@Override

protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_gcm_register);


   RegisterBackground task = new RegisterBackground();

   task.setContext(getBaseContext());

   task.execute();

}
// inner class that sends GCM registration request and receive registration id.
class RegisterBackground extends AsyncTask<String,String,String>{
   Context ctx;
   public void setContext(Context ctx){
      this.ctx = ctx;
   }
@Override

public String doInBackground(String... arg0) {
   String msg = "";
   String errMsg = "";
   try {
      String regId = GoogleCloudMessaging.getInstance(ctx).register("Your PROJECTCODE");
      msg = "Dvice registered, registration ID=" + regId;
      Log.i("GCMRegister.RegisterBackground", msg);
      if(regId != null){
         sendMyInfo(regId);
      }
   } catch (IOException ex) {
      errMsg = "Error :" + ex.getMessage();
      Log.e("GCMRegister.RegisterBackground", errMsg, ex);
   }
   return errMsg;
}
}
 
public void sendMyInfo(String regId){
    // TODO add your code to send GCM registration id to your server system.


Code igniter multiple file upload.

1. Prepare upload form view.

<< uploadview.php >>

<html>
<head>
<title>Upload Form</title>
</head>
<body>
<h2> file upload example </h2>
Only image files(gif|jpg|png) can be accepted. <br /> <br />
<?php echo $error;?>
<?php echo form_open_multipart('upload/do_upload');?>
<input type="file" name="userfile" size="20" /><br /><br />
<input type="file" name="userfile2" size="20" />
<br /><br />
<input type="submit" value="upload" />
</form>
</body>
</html>

2. Prepare uploadsuccess page view.

<< uploadsuccess.php >>

<html>
<head>
<title>Upload Form</title>
</head>
<body>
<h3>Your file was successfully uploaded!</h3>
<table ><tr valign=top><td>
<ul>
<?php foreach ($upload_data as $item => $value):?>
<li><?php echo $item;?>: <?php echo $value;?></li>
<?php endforeach; ?>
</ul>
<img src="/uploads/<?php echo $upload_data["file_name"]?>">
</td><td>
<ul>
<?php foreach ($upload_data2 as $item => $value):?>
<li><?php echo $item;?>: <?php echo $value;?></li>
<?php endforeach; ?>
</ul>
<img src="/uploads/<?php echo $upload_data2["file_name"]?>">
</td></tr></table>
<p><?php echo anchor('upload', 'Upload Another File!'); ?></p>
</body>
</html>

3. Prepare upload controller.

<< upload.php >>

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Upload extends CI_Controller {
    public function __construct() {
        parent::__construct();
    }

   function index()
   {
     $data['error'] = '';
     $this->load->view('uploadview', $data);
   }
   function do_upload()
   {
     $this->load->helper(array('form', 'url'));
     $config['upload_path'] = 'C:\wamp\www\uploads';
     $config['allowed_types'] = 'gif|jpg|png';
     $config['max_size'] = '100';
     $config['max_width']  = '1024';
     $config['max_height']  = '768';
     $this->load->library('upload', $config);

     $result = $this->upload->do_upload("userfile");
     if (!$result){
         $error = array('error' => $this->upload->display_errors());
         echo $this->upload->display_errors();
         $this->load->view('uploadview', $error);
         return;
     }
     $data = array('upload_data' => $this->upload->data());
     $result2 = $this->upload->do_upload("userfile2");
     if (!$result2){
         $error = array('error' => $this->upload->display_errors());
         echo $this->upload->display_errors();
         $this->load->view('uploadview', $error);
         return;
     }
     $data['upload_data2'] = $this->upload->data();
     $this->load->view('uploadsuccess', $data);
     }
}

4. You can find more information from this user-guide page.

http://ellislab.com/codeigniter/user-guide/libraries/file_uploading.html

Friday, April 11, 2014

How to use Android Google Maps(API Ver2) in older Android version such as 2.2.(Part 2/2)

1. Create new Android Application.
  • Go to File>New>Project.
  • Select Android>Android Application Project and click Next>.
  • Enter applciation name.
  • Enter package name. This should be the same package name you used when you created API key.
  • Select API 8: Android 2.2 (Froyo) in Minimu Required SDK.
  • Keep others as default and finish.
2. Load 'google-play-services_lib' to your project.(The same instructed in Part 1/2)
  • select Project>properties and go to Android.
  • In the Library box click 'Add...' button.
  • select 'google-play-services_lib' on the popup and click 'ok' button. 
 
3. Create New Activity and Layout.
  • Go to File>New>Others.
  • Select Android>Android Activity and click Next to the end.
  • Add google map fragment to your layout xml file.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
   <fragment
     android:id="@+id/gmap"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     class="com.google.android.gms.maps.SupportMapFragment"/>   
</LinearLayout>
 
4. Modify Actvity Class to handle google maps.
  • You may find some useful codes to control gmap. 
  • You can extends GMapActivity from FragmentActivty rather than ActionBarActivity.
package com.example.googlemaptest;
 
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
 
public class GMapActivity extends ActionBarActivity {
private GoogleMap _gMap;
private int _mapType = GoogleMap.MAP_TYPE_NORMAL;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_gmap);
      Bundle extras = this.getIntent().getExtras();
      Location location = null;

      if (extras != null && extras.containsKey("GPSINFO")) {
           location = (Location)extras.get("GPSINFO");
      }
      FragmentManager fragmentManager = getSupportFragmentManager();
      SupportMapFragment mapFragment = (SupportMapFragment)
      fragmentManager.findFragmentById(R.id.gmap);
      _gMap = mapFragment.getMap();
      _gMap.getUiSettings().setCompassEnabled(true);
      _gMap.getUiSettings().setZoomControlsEnabled(true);
      _gMap.getUiSettings().setMyLocationButtonEnabled(true);
      _gMap.getUiSettings().setAllGesturesEnabled(true);
      _gMap.getUiSettings().setMyLocationButtonEnabled(true);
      _gMap.getUiSettings().setRotateGesturesEnabled(true);
      _gMap.getUiSettings().setTiltGesturesEnabled(true);
      _gMap.getUiSettings().setZoomGesturesEnabled(true);
      _gMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);

      LatLng sfLatLng = null;
      if(location != null){
      double lat = location.getLatitude();
      double lng = location.getLongitude();
      sfLatLng = new LatLng(lat, lng);
      Geocoder geocoder = new Geocoder(this, Locale.getDefault());
      List<Address> addresses = null;
      try {
      addresses = geocoder.getFromLocation(lat, lng, 1);
      } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }
      if(addresses != null){
      _gMap.addMarker(new MarkerOptions()
      .position(sfLatLng)
      .title("Position in " + addresses.get(0).getAddressLine(1) + " " + addresses.get(0).getAddressLine(2))
      .snippet(addresses.get(0).getAddressLine(0))
      .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
      }else{
      _gMap.addMarker(new MarkerOptions()
      .position(sfLatLng)
      .title("Position")
      .snippet("No address is available")
      .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))); 
      }
      _gMap.animateCamera(CameraUpdateFactory.newLatLngZoom(sfLatLng, 13));
      }else{
      }
   }

5. Change Manifast file.

  • add uses-feature.
  • add premission.
  • add meta-data for API key.
  • add meta-data for gms version.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.example.googlemaptest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
 

<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
 

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 

<application
        ...  >
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="AIASDFASlSG6qfsadfdfZtZVnuZTJyfsSDFSD2" />
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
 
6. Call GMapActivity
  • You can add this code  to call GMapActvity. 
Location location = new Location("You are here");
location.setLatitude(latitude);
location.setLongitude(longitude);

Intent intent = new Intent(getBaseContext(), GMapActivity.class);
intent.putExtra("GPSINFO", location);
startActivity(intent);  

  • In some older verion android phone google play service should be updated.
  • In the case of content filtering message, go to Menu>Settings in Google Play Store and unlock Content Filtering in User Controls. 

How to use Android Google Maps(API Ver2) in older Android version such as 2.3.(Part 1/2)

1. Install google play service package.
  • Go to Android SDK manager.
  • Select Google Play services under Extras and click 'Install packages' button.
 
  • Accept License agreement and click 'Istall' button.
 2. Import the downloaded google play service.
  • Select file>Import>Android>Existing Android Code Into Workspace in eClipse.
  • Click 'Browse...' button and select google play service folder(adt home>sdk>extras>google>google_play_service).
  • Select google-play-services_lib and click 'Finish' button.
  • You can now see 'google-play-services_lib' project in Package Explore in eClipse.
3. Load 'google-play-services_lib' to your project.
  • select Project>properties and go to Android.
  • In the Library box click 'Add...' button.
  • select 'google-play-services_lib' on the popup and click 'ok' button. 
  

 4. Obtain Android Google Maps V2 API key.
  • go to Window>Preferences and select Android>Build.
  • Copy SHA1 fingerprint.(You can also get it from command line using keytool.)
  • go to google cloud console(https://cloud.google.com/console).
  • Create project if you don't have on yet.
  • Switch on Google Maps Android API v2 in APIs & Auth>APIs.
  • go to APIs & auth>Credentials and click 'Create New Key' button under Public API access.
  • Select Android Key in the 'Create New Key' popup.
  • Insert SHI;Your Package Name as instructed. ex) 45:B5:E4:6F:36:AD:0A:98:94:B4:02:66:2B:12:17:F2:56:26:A0:E0;com.example.googlemaptest
  • The package name should be in the AndroidManifest.xml of your app project.
  • Copy the API key created and add it as a meta-data in the AndroidManifest.xml of your app project as below.
<application
android:name=...>
      <meta-data android:name="com.google.android.maps.v2.API_KEY"
                    android:value="AIasdfsvsdfe9UzZtZVnuZTJy2SSDFSDFF3" />



Thursday, April 3, 2014

Tropical Fish...

This is not a fish... it's me.

This also is not a fish... it's a coral.

Fish near Cebu.
Nimo???

 
Fish near Saipan.
Sharks !!.

Tuesday, April 1, 2014

MySQL change character set

Change character set in MySQL.

1. Change character set in MySQL console.
  • check default character set.
> show variables like 'char%';
  • Change character set to the character set you want, for example, 'euckr'.
> set character set euckr;

2. If your talbes had been already created before you changed the character set, you might need to change the default character sets of the tables.
  • Check character set of your table.
> show create table [your databasename].[your tablename];
  • Change character set of the table.
> alter table [your databasename].[your tablename] convert to charset euckr;
> alter table [your databasename].[your tablename] convert to charset utf8;