Pemilihan Koneksi Data Blackberry Secara Otomatis

Posted: 15 Februari 2011 in Mobile, Networking, Programming
Tag:, , , ,

Dalam mengembangkan aplikasi Java (J2ME) yang membutuhkan koneksi data (internet) pada platform blackberry, terdapat penambahan sufiks pada URL-nya dimana hal ini tidak terdapat pada platform yang lain. Penambahan sufiks ini bertujuan untuk memberitahukan kepada sistem jalur / konfigurasi koneksi data yang akan dipakai. Adapun sufiks-sufiks tersebut seperti :

  1. http://%5Bdomain/alamatIP%5D{/sub_path};interface=wifi : Koneksi data yang dipakai adalah WiFi
  2. http://%5Bdomain/alamatIP%5D{/sub_path};deviceside=false : Koneksi data yang dipakai adalah melalui BES (Blackberry Enterprise Server)
  3. http://%5Bdomain/alamatIP%5D{/sub_path};deviceside=false;ConnectionType=mds-public : Koneksi data yang dipakai adalah melalui BIS (Blackberry Internet Service)
  4. http://%5Bdomain/alamatIP%5D{/sub_path};deviceside=true;apn=<apn_name> : Koneksi data yang dipakai adalah TCP (direct connection) dimana terdapat opsional parameter user authentication untuk APN (Access Point Name) terkait jika dibutuhkan (;tunnelauthusername=<username>;tunnelauthpassword=<password>)
  5. Sufiks konfigurasi yang lain dapat dilihat di dokumentasi API Blackberry.

Untuk menangani pemakaian jalur koneksi data tersebut terdapat dua cara yaitu secara manual, baik itu hard-coded maupun penyediaan fasilitas pemilihan koneksi pada aplikasi (misalnya berupa layar/dialog pengaturan), serta secara otomatis yaitu aplikasi menentukan sendiri koneksi data yang akan dipakai berdasarkan koneksi data yang tersedia pada saat runtime dengan prioritas tertentu. Pemilihan koneksi data secara otomatis oleh aplikasi tentu akan memberikan kemudahan bagi pemakai aplikasi nantinya dimana tidak dibingungkan oleh pengaturan-pengaturan koneksi data yang mungkin tidak dimengerti oleh pengguna awam.

Untuk mewujudkan hal tersebut maka terlebih dahulu kita mengimplementasikan fungsi untuk mengenali dan memeriksa ketersediaan koneksi-koneksi data yang ada pada perangkat blackberry. Yang pertama adalah fungsi untuk mengenali dan memeriksa koneksi WiFi, dimana terdapat 2 implementasi fungsi, yaitu fungsi untuk memeriksa apakah perangkat WiFi tersedia serta fungsi untuk memeriksa apakah ada koneksi WiFi yang aktif. Berikut implementasi fungsinya :

public static boolean isWifiAvailable()
// cek apakah ada koneksi wifi tersedia
{
	return RadioInfo.areWAFsSupported(RadioInfo.WAF_WLAN);
}
public static boolean isWifiActive()
// cek apakah koneksi wifi aktif / on
{
	return (RadioInfo.getActiveWAFs() >= RadioInfo.WAF_WLAN);
}

public static boolean isWifiConnected() 
// cek apakah koneksi wifi terhubung
{
        return (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED);
}

Kemudian fungsi untuk memeriksa apakah data bearer dalam kondisi offline. Fungsi ini nantinya digunakan untuk menentukan penggunaan koneksi data melalui BES maupun BIS dimana kedua koneksi tersebut dapat digunakan jika data bearer tidak offline. Adapun implementasi fungsinya adalah sebagai berikut :

public static boolean isDataBearerOffline() {
	return RadioInfo.getState()==RadioInfo.STATE_OFF ||
		   RadioInfo.getSignalLevel() == RadioInfo.LEVEL_NO_COVERAGE;
}

Fungsi pengenalan koneksi terakhir adalah untuk memeriksa apakah koneksi melalui BIS tersedia. Hal ini dilakukan dengan melakukan iterasi pada IPPP service book untuk memeriksa apakah terdapat koneksi BIS. Adapun implementasi fungsinya adalah sebagai berikut :

public static boolean isBISAvailable()
{
    	boolean _bisSupport = false;
        // Iterasi IPPP service-book (merepresentasikan jalur data untuk MDS dan BIS-B)
        ServiceBook sb = ServiceBook.getSB();
        ServiceRecord[] records = sb.findRecordsByCid( "IPPP" );
        if( records == null ) {
            return _bisSupport;
        }
        int numRecords = records.length;
        for( int i = 0; i < numRecords; i++ ) {
            ServiceRecord myRecord = records[i];
            String name = myRecord.getName();    
            String uid = myRecord.getUid();      
            // First of all, the CID itself should be equal to IPPP if this is going to be an IPPP service book.
            if( myRecord.isValid() && !myRecord.isDisabled() ) {
                // Now we need to determine if the service book is Desktop or BIS. 
                int encryptionMode = myRecord.getEncryptionMode();
                if( encryptionMode == ServiceRecord.ENCRYPT_RIM ) {
                } else {
                    _bisSupport = true;
                }
            }
        }
        return _bisSupport;
}

Selain itu kita juga perlu mengenali koneksi yang menggunakan WAP dan memeriksa apakah tersedia sebagai opsi koneksi tambahan :

    public static String connectionUID = "";
    public static boolean isWAPavailable() {
        ServiceBook sb = ServiceBook.getSB();
        ServiceRecord[] records = sb.findRecordsByCid("WPTCP");
        connectionUID = "";
        for (int i = 0; i < records.length; i++) {
            if (records[i].isValid() && !records[i].isDisabled()) {
                if (records[i].getUid() != null &&
                    records[i].getUid().length() != 0) {
                    if ((records[i].getCid().toLowerCase().indexOf("wptcp") != -1) &&
                        (records[i].getUid().toLowerCase().indexOf("wifi") == -1) &&
                        (records[i].getUid().toLowerCase().indexOf("mms") == -1)   ) {
                        connectionUID = records[i].getUid();
                        return true;
                    }
                }
            }
        }
        return false;
    }

Setelah kita mengimplementasikan fungsi-fungsi yang menangani pemeriksaan ketersediaan koneksi-koneksi data pada Blackberry, maka terakhir adalah membuat fungsi untuk menentukan sufiks URL yang akan digunakan. Pada fungsi ini juga diterapkan urutan prioritas koneksi data yang akan digunakan sehingga sebenarnya implementasi fungsi ini berbeda-beda dimana bersesuaian dengan kebutuhan aplikasi / pembuat aplikasi. Adapun implementasi fungsi ini adalah sebagai berikut :

public static String DeviceConnectionExtension()
// Penentuan Sufiks URL
{
        // 1. SIMULATOR
        if(DeviceInfo.isSimulator()) {
            return "";
        }
        // 2. WIFI 
        if (isWifiActive() && isWifiAvailable() && isWifiConnected()) {
            return ";interface=wifi";
        }
        // 3. BIS 
        if (!isDataBearerOffline() && isBISAvailable() && CoverageInfo.isCoverageSufficient(4)) {
            return ";deviceside=false;ConnectionType=mds-public";
        }
        // 4. BES 
        if (!isDataBearerOffline() && CoverageInfo.isCoverageSufficient(2)) {
            return ";deviceside=false";
        }
        // 5. WAP
        if (isWAPavailable() && CoverageInfo.isCoverageSufficient(1)) {
            return ";ConnectionUID="+connectionUID;
        }        
        // 6. TCP (opsi terakhir / default)
        return ";deviceside=true";
}

Fungsi terakhir digunakan saat memberikan parameter URL pada objek HttpConnection, seperti yang dicontohkan pada cuplikan kelas untuk keperluan koneksi data di bawah ini :

public static final int URLENCODED = 0;
public static final int MULTIPART = 1;    
private static final String BOUNDARY = "----------Q2keYFl144hkeyZCa144jz";

    public static HttpConnection makeConnection(String url, Hashtable params, String[] fileField, String[] fileName, String[] fileType, byte[][] fileBytes) {
        try {
            return makeConnection(url, getHttpMultipartRequestData(params, fileField, fileName, fileType, fileBytes), ServerConnection.MULTIPART);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public static HttpConnection makeConnection(String url, byte[] postData) {
        return makeConnection(url, postData, ServerConnection.URLENCODED);
    }

    public static HttpConnection makeConnection(String url, byte[] postData, int mode) {
        HttpConnection conn = null;
        OutputStream out = null;
        try
        {
            conn = (HttpConnection) Connector.open((url.indexOf("http://") == 0 ? "" : "http://") + url + DeviceConnectionExtension());
            if (postData == null) {
                conn.setRequestMethod(HttpConnection.GET);
            } else {
                conn.setRequestMethod(HttpConnection.POST);
                conn.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.0");
                if (mode == ServerConnection.URLENCODED) conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                else conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + ServerConnection.BOUNDARY);
                conn.setRequestProperty(HttpProtocolConstants.HEADER_CONTENT_LENGTH, String.valueOf(postData.length));
                out = conn.openOutputStream();
                out.write(postData);
            }
        } catch (IOException e) {
            //e.printStackTrace();
        } finally {
            if (out != null) try {out.close();} catch (IOException e2) {}
        }
        return conn;
    }

    public static byte[] getResponse(HttpConnection conn) {
        return getResponse(conn, false);
    }

    public static byte[] getResponse(HttpConnection conn, boolean secondTry) {
        byte[] response = null;
        if (conn != null) {
            DataInputStream in = null;
            ByteArrayOutputStream baos = null;
            try {
                if (conn.getResponseCode() == HttpConnection.HTTP_OK) {
                    in = new DataInputStream(conn.openInputStream());
                    baos = new ByteArrayOutputStream();
                    byte[] b = new byte[2048];
                    int count = 0;
                    while (count != -1) {
                        count = in.read(b, 0, b.length);
                        if (count != -1) baos.write(b, 0, count);
                    }
                    response = baos.toByteArray();
                } else if (conn.getResponseCode() == HttpConnection.HTTP_TEMP_REDIRECT
                  || conn.getResponseCode() == HttpConnection.HTTP_MOVED_TEMP
                  || conn.getResponseCode() == HttpConnection.HTTP_MOVED_PERM) {
                    String location = conn.getHeaderField("location").trim();
                    if (!location.equals("") && !secondTry) {
                        response = getResponse(makeConnection(location, null), true); // second try redirection HTTP_GET
                    }
                } else {
                    in = new DataInputStream(conn.openInputStream());
                    baos = new ByteArrayOutputStream();
                    byte[] b = new byte[2048];
                    int count = 0;
                    while (count != -1) {
                        count = in.read(b, 0, b.length);
                        if (count != -1) baos.write(b, 0, count);
                    }
                    response = baos.toByteArray();
                }
            } catch (Exception e) {
                //e.printStackTrace();
            } finally {
                if (in != null) try {in.close();} catch (IOException e) {}
                if (baos != null) try {baos.close();} catch (IOException e) {}
                try {conn.close();} catch (IOException ex) {}
            }
        }
        return response;
    }

Dengan demikian maka penentuan koneksi data pada akhirnya akan otomatis ditentukan saat aplikasi berjalan (runtime) tanpa membutuhkan peran serta pengguna aplikasi dalam menentukannya.

Komentar
  1. iis mengatakan:

    mantap joel, crot lah,haha

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s