Saturday, March 15, 2014

Using UCM's RIDC to Check In Document in UCM from Java

Blog ini akan membahas bagaimana menggunakan API yang disediakan Webcenter Content (Universal Content Management System/UCM) untuk mengakses, menambahkan ataupun memodifikasi dokumen-dokumen yang ada di dalamnya. UCM menyediakan API yang disebut RIDC (Remote Intradoc Client) untuk mengeksekusi fungsionalitas dan fungsi-fungsi yang ada di UCM tanpa perlu langsung mengakses sistem. RIDC cocok digunakan apabila seseorang ingin membangun aplikasi Document Management yang menyimpan dokumen ke UCM, tapi ingin membangun sendiri antar mukanya tanpa menggunakan User Interface UCM.

Diharapkan anda sudah mengerti dan cukup familiar dengan Oracle Webcenter Content (Universal Content Management System/UCM) agar dapat memahami apa yang tertulis di blog ini.

Sebelum menggunakan RIDC, project yang anda buat harus meng-include file jar berikut:

oracle.ucm.ridc-11.1.1.jar

File ini dapat diambil di folder server tempat anda meng-instal Webcenter Content.

Contoh berikut dapat dipakai untuk melakukan Check In dokumen ke UCM berikut metadata-nya.
Penjelasan code saya lampirkan dalam bentuk comment "// comment", silahkan reuse code ini sebagaimana perlu.

package com.nostratech.jasper.service.generator;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import oracle.stellent.ridc.IdcClient;
import oracle.stellent.ridc.IdcClientException;
import oracle.stellent.ridc.IdcClientManager;
import oracle.stellent.ridc.IdcContext;
import oracle.stellent.ridc.model.DataBinder;
import oracle.stellent.ridc.model.DataObject;
import oracle.stellent.ridc.model.DataResultSet;
import oracle.stellent.ridc.model.TransferFile;
import oracle.stellent.ridc.protocol.ServiceResponse;

public class UCM {
    private  IdcClientManager myIdcClientManager;
    private  IdcClient myIdcClient;
    private  IdcContext myIdcContext;
    public String addContent(String fileName,String dDocTitle){
        
        try {
            // Instantiate IdcClientManager untuk menginisiasi koneksi ke server UCM
             myIdcClientManager = new IdcClientManager();
             // masukkan nama Server UCM anda dan port RIDC
             // Default Port adalah 4444 (anda dapat mengubahnya melalui Enterprise Manager
             myIdcClient=myIdcClientManager.createClient("idc://ServerHostName:4444");
             
             myIdcContext = new IdcContext("sysadmin");
             ServiceResponse myServiceResponse = null;
                InputStream fileStream = null;
                
                fileStream = new FileInputStream(fileName);
                long fileLength = new File(fileName).length();
                
                // Data binder akan menyimpan pasangan metadata dan value
                // Misal: myRequestDataBinder.putLocal("dDocAuthor", "Darwin");
                // Ini akan menyimpan pasangan metadata dDocAuthor = Darwin
                // Apabila kita melakukan check in, maka Author document akan di-set menjadi Darwin
                // Apabila kita melakukan search, maka dokumen yang dicari adalah yang Author-nya adalah Darwin
                
                DataBinder myRequestDataBinder = myIdcClient.createBinder();
                
                // Nama service UCM yang akan dipanggil (Check in, Search dsb.)
                // Dalam kasus ini adalah Check in
                // Anda dapat melihat list service-service di tab Administrator 
                myRequestDataBinder.putLocal("IdcService", "CHECKIN_UNIVERSAL");
                myRequestDataBinder.putLocal("dDocType", "Application");
                // Judul Dokumen
                myRequestDataBinder.putLocal("dDocTitle", dDocTitle);
                // Nama Author dokumen
                myRequestDataBinder.putLocal("dDocAuthor", "darwin");
                // Security Group, anda dapat membuat custom security group atau memanfaatkan default (Public)
                myRequestDataBinder.putLocal("dSecurityGroup", "Public");
                myRequestDataBinder.putLocal("dDocAccount", "");
                
                // Format Dokumen
                myRequestDataBinder.putLocal("dFormat", "text/html");
                
                // Folder di UCM, tempat kita akan menyimpan Dokumen 
                // Folder yang secara default ada di UCM adalah Contribution Folder
                // Value untuk Parameter xCollectionID adalah ID Folder, bukan string
                // Untuk itu, kita menggunakan getFolderIDFromPath untuk menentukan ID dari Contribution Folder
                
                myRequestDataBinder.putLocal("xCollectionID",
                Long.toString(getFolderIdFromPath("/Contribution Folders/")));
                
                // File yang akan kita check in
                myRequestDataBinder.addFile("primaryFile",new TransferFile(fileStream, fileName, fileLength, "text/html"));
                myServiceResponse = myIdcClient.sendRequest(myIdcContext,myRequestDataBinder);
                
                String myResponseString =myServiceResponse.getResponseAsString();
        
                System.out.println("Uploaded file details: \n" +myResponseString);

                
                // Cek hasil API call
                DataBinder binder = myServiceResponse.getResponseAsBinder();
                    System.out.println("End");
                    
                    // Ambil URL dokumen setelah di-check in
                    String docUrl=binder.getLocal("WebfilePath");
                      int index=docUrl.lastIndexOf("groups/");
                      String folder=docUrl.substring(index, docUrl.length());
                       System.out.println( index + "entered string is: "+folder);
                      index=0;
                        index=folder.lastIndexOf("~");
                        folder=folder.substring(0,index);
                     // return hasil URL check in
                    return "http://hostname/cs/"+folder+".pdf";
                    
        } catch (IdcClientException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "failed";
    

    }
    
    // ambil ID dari sebuah Folder
    // Parameter adalah String Nama Folder, me-return ID dari folder tersebut jika ada di UCM
    private long getFolderIdFromPath(String myFolderPath) {

        ServiceResponse myServiceResponse = null;
        Long myFolderId = null;
        try {
            
            DataBinder myRequestDataBinder = myIdcClient.createBinder();
            // gunakan service COLLECTION_INFO untuk mendapatkan informasi folder
            myRequestDataBinder.putLocal("IdcService", "COLLECTION_INFO");
            
            
            myRequestDataBinder.putLocal("hasCollectionPath", "true");
            // ambil collection path dari folder yang ingin dicari
            myRequestDataBinder.putLocal("dCollectionPath", myFolderPath);
            myServiceResponse = myIdcClient.sendRequest(myIdcContext,
            myRequestDataBinder);
            DataBinder myResponseDataBinder =
            myServiceResponse.getResponseAsBinder();
            DataResultSet myDataResultSet =
            myResponseDataBinder.getResultSet("PATH");
            DataObject myDataObject =
            myDataResultSet.getRows().get(myDataResultSet.getRows().size() - 1);
            
            // ambil ID dari collection yang kita cari
            myFolderId = new Long(myDataObject.get("dCollectionID"));
            System.out.println("Folder id: " + myFolderId);
        } catch (IdcClientException idcce) {
        System.out.println("IDC Client Exception occurred. Unable to retrieve folder id from path. Message: " + idcce.getMessage() +" Stack trace: ");
            idcce.printStackTrace();
            } catch (Exception e) {
            System.out.println("Exception occurred. Unable to retrieve folder id from path. Message: " + e.getMessage() + ", Stack trace: ");
            e.printStackTrace();
            } finally {
            if (myServiceResponse != null) {
            myServiceResponse.close();
            }
            }
        return 0;
    }
    

}



Anda dapat menggunakan potongan code diatas untuk bermacam-macam ide.
Sebagai contoh, saya menggunakn code diatas dalam sebuah aplikasi Jasper yang men-generate file .pdf. Ketika Jasper saya meng-generate sebuah dokumen PDF, saya memanggil method diatas: addContent(lokasiFileYangInginDiupload, namaDokumenSetelahDimasukkanKeUCM). Secara otomatis semua report yang di-generate di Jasper saya juga akan ter-archive ke UCM untuk pencarian lebih lanjut di masa yang akan datang.
Anda dapat bereksplorasi untuk menggunakan API UCM untuk bermacam-macam kegunaan dalam document management. Selamat Mencoba!


Have fun!



Understanding Webcenter Content - Create Custom Profile and Fields


Oracle Webcenter Content atau yang dulu dikenal dengan UCM merupakan sebuah Document Management System yang dapat dipakai untuk mengatur life-cycle dokumen. Disini, kita dapat menyimpan (check-in) dokumen elektronik untuk disimpan, di-download, versioning, edit atau diatur masa hidupnya. 

Untuk check in dokumen, secara default, sudah ada metadata yang dapat kita input untuk menentukan detail suatu dokumen (misal: author, tanggal, comment dsb.). Akan tetapi biasanya ini tidak cukup apabila kita datang ke suatu client yang memiliki dokumen khusus dan metadata yang berbeda dengan apa yang disediakan. Untuk itu, kita dapat membuat Profile untuk membedakan metadata dari dokumen-dokumen yang akan disimpan ke dalam UCM.

Misal KTP, data isiannya adalah Nomor KTP, Nama Lengkap, Tanggal Lahir, Golongan Darah dst. Sedangkan NPWP hanya terdiri dari Nama Lengkap dan Nomor NPWP. Untuk kebutuhan ini, kita dapat membuat 2 buah Profile yaitu KTP dan NPWP, dimana ketika user meng-input dokumen ini, hanya field-field yang bersangkutan yang akan muncul. Hal ini memudahkan pencarian dan juga pengelompokan dokumen.

Dalam blog ini, saya akan mencoba menjelaskan bagaimana menambahkan Field tambahan diluar yang sudah ada, dan juga membuat profile Check in baru dengan input yang sesuai metadata yang diperlukan.

Pertama-tama, Log in dengan menggunakan account Administrator.

Buka Accordion Administration -> Admin Applets -> Configuration Manager


Disini anda dapat melihat daftar field-field yang ada di sistem, Table, View dan juga menambahkan Rules dan Profile di UCM.


Di Tab Information Fields, klik tombol Add untuk menambahkan field baru. Jika penasaran, field-field ini akan juga ditambahkan ke database anda, di tabel DOCMETA, dengan nama kolom x<NAMA_FIELD> (misal xNamaDokumen).

Disini kita akan menambahkan 2 Field baru yaitu NamaDokumen dan TipeDokumen. NamaDokumen akan berupa input text biasa, sedangkan TipeDokumen adalah drop down list yang dapat dipilih valuenya.



Untuk membuat field yang berupa Drop Down value atau Select One Choice, pilih check box Enable Option List. Kemudian tekan tombol Configure.


Pilih Use Option List, beri nama list tersebut, lalu klik tombol Edit.


Layar akan terbuka. Disini kita dapat mengisi Value dari drop down TipeDokumen. Setiap value dipisahkan dengan tanda 'Enter'. Misal kita ingin field TipeDokumen memiliki pilihan Hasil Scan, Word, Excel, PDF dan Lain-lain, maka di layar Option List kita memasukkan value berikut:

Hasil Scan
Word
Excel
PDF
Lain-lain



Rules -> Add


Tambahkan name dan description untuk Rule baru yang akan dibuat.


Pilih metadata yang akan ditampilkan bersama dengan rule ini. Rule yang berbeda dapat diset untuk menampilkan kumpulan metadata yang berbeda. Dalam kasus ini, kita akan meng-include NamaDokumen dan TipeDokumen yang kita buat sebelumnya.


Kita dapat menentukan field-field yang kita pilih apakah field tersebut editable, hidden, required dsb.


Misal kita memilih atribut tersebut menjadi Required, kita dapat memasukkan Required Message untuk membantu user.


Hasil akhirnya adalah field-field yang kita tambahkan, berikut tipe-nya pada rule yang telah kita buat.



Berikutnya kita akan membuat sebuah field baru untuk men-trigger perubahan rule yang kita buat. Kita akan membuat field bernama ProfileSelector yang berupa List. List ini nantinya digunakan untuk memilih Rule mana yang akan ditampilkan untuk proses check-in dokumen.




Disini kita akan membuat pilihan Tipe Dokumen 1 dan Tipe Dokumen 2


Apabila telah selesai, kembali ke tab Profiles. Pilih Trigger Field, disini kita akan men-specify field mana yang akan digunakan sebagai trigger perubahan Profile. Gunakan field ProfileSelector yang baru kita buat.


Buat profile berdasarkan value dari field ProfileSelector. Misal kita membuat Profile KTP untuk pilihan Tipe Dokumen 1, atau NPWP untuk Tipe Dokumen 2.



Pilih rules di bagian Rules. Disini kita mementukan rules mana (dan atribut apa saja berdasarkan rule tersebut) yang akan dimunculkan di profile ini.


Setelah selesai refresh page Webcenter anda. Kita dapat melihat profile dokumen yang baru kita buat di New Check In -> Nama Profile yang kita buat


Apabila kita memilih profile tersebut, kita dapat melihat bahwa field check in terdiri dari metadata wajib dan juga metadata yang telah kita specify sebelumnya di bagian profile.

Field-field ini juga dapat di-custom agar memiliki label yang berbeda, ditampilkan atau tidak, dsb. Semuanya dapat dilakukan dengan menggunakan applet Configuration Manager.


Di bagian bawah, kita dapat melihat dua field yang baru kita buat: Nama Dokumen dan Tipe Dokumen. Nama Dokumen berupa input text biasa dan Tipe Dokumen merupakan Select One Choice dengan pilihan Hasil Scan, Word, Excel, PDF dan Lain-lain, sesuai dengan yang telah kita definisikan sebelumnya.



Anda dapat mengulangi langkah-langkah diatas untuk membuat halaman check in dengan metadata custom sesuai dengan kebutuhan anda.

Selamat mencoba dan semoga membantu!


Moving OHS Instance with Movement Scripts


Menurut Oracle Enterprise Deployment Guide, sebaiknya Oracle HTTP Server (OHS) di-deploy di web tier yang terpisah dengan application tier. Konfigurasi demikian memiliki keuntungan terutama dari sisi keamanan. Jika mesin OHS terkompromi, backend application dan backend database masih aman karena berada pada tier yang berbeda (subnet isolation, firewall, dsb.) Namun tidak jarang pada masa development mesin yang tersedia terbatas, sehingga OHS 'terpaksa' di-deploy di mesin yang sama dengan backend application. Lalu bagaimana ketika pindah ke production environment?

Oracle Enterprise Deployment Topology

Oracle menyediakan movement scripts untuk memfasilitasi tipe kebutuhan seperti ini. Sebelum menjalankan script tersebut, pastikan file dan script berikut ini tersedia:
  • $ORACLE_COMMON/jlib/cloningclient.jar
  • $ORACLE_COMMON/bin/copyBinary.sh
  • $ORACLE_COMMON/bin/pasteBinary.sh
  • $ORACLE_COMMON/bin/copyConfig.sh
  • $ORACLE_COMMON/bin/extractMovePlan.sh
  • $ORACLE_COMMON/bin/pasteConfig.sh
  • $ORACLE_COMMON/bin/obfuscatePassword.sh

Dengan mengasumsikan $JAVA_HOME$MW_HOME dan $ORACLE_HOME untuk komponen OHS telah tersedia pada masing-masing mesin, berikut adalah langkah-langkahnya.
  1. Topologi yang akan menjadi bahan percobaan kita adalah sebuah domain yang bernama  Blog_Domain terdiri dari AdminServer, WLS_App1, dan ohs1.
    Farm_Blog_Domain
  2. Pada saat semua komponen sedang berjalan, buat archive web1.jar yang berisi konfigurasi dari OHS_Instance1 dengan script copyConfig.sh.
    [oracle@machine1 ~] $ cd /u01/app/oracle/product/fmw/oracle/common/bin
    [oracle@machine1 bin] $ ./copyConfig.sh -javaHome /u01/app/oracle/product/fmw/jrockit-jdk1.6.0 -archiveLoc ~/web1.jar -sourceInstanceHomeLoc /u02/app/oracle/admin/OHS_Instance1 -logDirLoc ~/copyConfigLogs
  3. Extract movement plan dari archive web1.jar pada machine1.
    [oracle@machine1 ~] $ cd /u01/app/oracle/product/fmw/oracle/common/bin
    [oracle@machine1 bin] $ ./extractMovePlan.sh -javaHome /u01/app/oracle/product/fmw/jrockit-jdk1.6.0 -archiveLoc ~/web1.jar -planDirLoc ~/web_plans -logDirLoc ~/extractMovementPlanLogs
  4. Script tersebut akan menghasilkan moveplan.xml di dalam direktori ~/web_plans yang berisi konfigurasi dari OHS instance yang telah kita copy sebelumnya. Kita dapat melakukan perubahan seperti property ServerName, WebLogicHost, WebLogicPort, dsb yang mungkin perlu kita sesuaikan ketika OHS instance kita pindahkan ke mesin lain. Apapun yang perlu diubah, pastikan hanya mengubah bagian yang ditandai dengen READ_WRITE. Pada artikel ini saya tidak akan melakukan perubahan selain mengubah ServerName dari machine1.nostratech.com menjadi machine2.nostratech.com
    ...
    <configProperty>
      <name>ServerName</name>
      <value>machine2.nostratech.com</value>
      <itemMetadata>
        <dataType>STRING</dataType>
        <scope>READ_WRITE</scope>
      </itemMetadata>
    </configProperty>
    ...
  5. Copy web1.jar dan direktori yang berisi moveplan.xml ke machine2. Clone konfigurasi OHS_Instance1 pada machine1 ke WT_Instance1 pada machine2 dengan menggunakan script pasteConfig.sh.
    [oracle@machine2 ~] $ cd /u01/app/oracle/product/fmw/oracle/common/bin
    [oracle@machine2 bin] $ ./pasteConfig.sh -javaHome /u01/app/oracle/product/fmw/jrockit-jdk1.6.0 -archiveLoc ~/web1.jar -movePlanLoc ~/web_plans/moveplan.xml -targetOracleHomeLoc /u01/app/oracle/product/fmw/web -targetInstanceHomeLoc /u02/app/oracle/admin/WT_Instance1 -targetInstanceName webtier1 -logDirLoc ~/pasteConfigLogs
  6. Daftarkan webtier1 ke Blog_Domain dengan menggunakan script opmnctl pada machine2.
    [oracle@machine2 ~] $ cd /u02/app/oracle/admin/WT_Instance1/bin
    [oracle@machine2 bin] $ ./opmnctl registerinstance -adminHost blogadminvhn.nostratech.com -adminPort 7001
  7. Topologi sekarang menjadi seperti berikut:
    Farm_Blog_Domain setelah webtier1 didaftarkan 
  8. Hapus web1 pada Blog_Domain dengan menggunakan script opmnctl pada machine1.
    [oracle@machine1 ~] $ cd /u02/app/oracle/admin/OHS_Instance1/bin
    [oracle@machine1 bin] $ ./opmnctl unregisterinstance
  9. Status topologi final adalah sebagai berikut:
    Farm_Blog_Domain setelah web1 dihapus
Selesai! Jika tidak menggunakan movement script, efeknya akan lebih terasa jika jumlah OHS yang ingin dipindahkan cukup banyak. Movement script tidak hanya dapat memindahkan Oracle instance, namun juga dapat digunakan untuk memindahkan Middleware binaries dan konfigurasi WebLogic domain. Selamat mencoba ya!

Friday, March 14, 2014

Google Map Android API

Setelah pada posting sebelumnya dibahas tentang Google map API javascript yang dipakai di web. Sekarang akan dibahas tetang penggunaan google map di device android.
Pertama masuk ke google developer console. Aktifkan api service google map android API v2

Kemudian create android key.




Create new android project dari IDE kita.
Tambahkan meta data berikut ke dalam AndroidManifest.xml di dalam tag <application>


 <meta-data  
   android:name="com.google.android.gms.version"  
   android:value="@integer/google_play_services_version" />  
 <meta-data  
   android:name="com.google.android.maps.v2.API_KEY"  
   android:value="YOUR_API_KEY"/>  

Tambahkan uses-permission berikut ini AndroidManifest.xml

 <uses-permission android:name="android.permission.INTERNET"/>  
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
 <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>  
 <!-- The following two permissions are not required to use  
    Google Maps Android API v2, but are recommended. -->  
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>  
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>  

Kemudian create library Google Play Service.
Caranya import project dari android sdk : <android-sdk>/extras/google/google_play_services/libproject/google-play-services_lib/

Di propertiesnya check as Library
Di project tadi ditambahkan library Google play service yang sudah kita buat ini.



Create android layout xml untuk menampung map.

 <?xml version="1.0" encoding="utf-8"?>  
 <fragment xmlns:android="http://schemas.android.com/apk/res/android"  
         xmlns:map="http://schemas.android.com/apk/res-auto"       
      android:id="@+id/map"  
      android:layout_width="match_parent"  
      android:layout_height="match_parent"  
      android:name="com.google.android.gms.maps.MapFragment"  
      />  


Panggil layout xml di java code Activity.

 @Override  
      protected void onCreate(Bundle savedInstanceState) {  
           super.onCreate(savedInstanceState);  
           setContentView(R.layout.fragment_map);  
      }  


Run android application, maka tampilannya kurang lebih seperti ini :



Beberapa contoh penggunaan android google map api :

1. Menampilkan Marker

Untuk menampilkan market digunakan class Marker.
Marker diAdd ke object map

 Marker marker = map.addMarker(new MarkerOptions()  
                     .position(LAT_LNG)  
                     .title("your base")  
                     );  

Position marker diset berdasarkan latitude longitude yang diinginkan

 public class SampleMap extends Activity {  
      private static final LatLng LAT_LNG = new LatLng(-6.175486, 106.825407);  
      private GoogleMap map;  
      private Marker marker;  
      @Override  
      protected void onCreate(Bundle savedInstanceState) {  
           super.onCreate(savedInstanceState);  
           setContentView(R.layout.fragment_map);  
           map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();  
           map.animateCamera(CameraUpdateFactory.newLatLngZoom(LAT_LNG, 15));  
           Marker marker = map.addMarker(new MarkerOptions()  
                     .position(LAT_LNG)  
                     .title("your base")  
                     );  
      }  



2. Action Event

Google map api menyediakan beberapa class untuk melakukan event interaksi dengan map.
Antara lain : setOnMapLongClickListener(), setOnMapClickListener(), setOnCameraChangeListener(), OnMyLocationButtonClickListener().

Contohnya : Event OnMapClickListener(), dijalankan saat map diklik atau ditouch. Event ini mengalikan nilai koordinat latititude longitude yg bisa kita olah nantinya.
Pada contoh kali ini pada saat map diklik akan muncul message berupa koordinat dimana area tesebut diklik.

 public class SampleMap extends Activity {  
      private static final LatLng LAT_LNG = new LatLng(-6.175486, 106.825407);  
      private GoogleMap map;  
      private Marker marker;  
      @Override  
      protected void onCreate(Bundle savedInstanceState) {  
           super.onCreate(savedInstanceState);  
           setContentView(R.layout.fragment_map);  
           map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();  
           map.animateCamera(CameraUpdateFactory.newLatLngZoom(LAT_LNG, 15));  
           map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {  
                @Override  
                public void onMapClick(LatLng arg) {  
                showToastMessage("lat : "+arg.latitude+"\nlng : "+arg.longitude);  
                }  
           });  
      }  
      public void showToastMessage(String message){  
           Toast.makeText(this, message, Toast.LENGTH_LONG).show();  
      }  



3. Menampilkan InfoWindow

Info window merupakan semacam popup yg muncul di map. Isinya bebas diisi content apa saja.
Untuk mengisi InfoWindow digunakan method snippet(), yang ada di Marker Option.


 map.addMarker(new MarkerOptions()  
           .position(position)  
           .title(title)  
           .snippet("CONTENT”)  
           );  


Untuk menampilkan InfoWindow panggil method showInfoWindow()

 public class SampleMap extends Activity {  
      private static final LatLng LAT_LNG = new LatLng(-6.175486, 106.825407);  
      private GoogleMap map;  
      private Marker marker;  
      @Override  
      protected void onCreate(Bundle savedInstanceState) {  
           super.onCreate(savedInstanceState);  
           setContentView(R.layout.fragment_map);  
           map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();  
           map.animateCamera(CameraUpdateFactory.newLatLngZoom(LAT_LNG, 15));  
           map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {  
                @Override  
                public void onMapClick(LatLng arg) {  
                     showMarkerAndInfoWindow("you are here", arg);  
                                    }  
           });  
      }  
      public void showMarkerAndInfoWindow( String title, LatLng position){  
           if(marker!=null){  
                marker.remove();  
                marker = null;  
           }  
           marker = map.addMarker(new MarkerOptions()  
           .position(position)  
           .title(title)  
           .snippet("you are in : \nlat : "+position.latitude+"\nlng : "+position.longitude)  
           );  
           marker.showInfoWindow();  
      }  

Pada contoh ini infoWindow akan dimunculkan pada saat map diklik. Kemudian akan muncul marker dengan infoWindow di atas marker berisi informasi koordinat dimana titik itu diklik.




Demikian sedikit tutorial tentang google map api di Android, semoga bisa membantu.
Selamat mencoba.

Terima kasih :)