Senin, 16 Desember 2019

Microsoft Windows 3.x AIO (All-In-One)

Setelah beberapa waktu yang lalu penulis mem-posting Microsoft Windows 9X AIO, pada kesempatan kali ini penulis membuat ISO CD dari koleksi sistem operasi Windows versi 3 yang penulis punya di HDD komputer lama penulis.

Untuk membuat ISO CD ini bootable, penulis tidak menggunakan ISOLINUX dan MEMDISK tetapi hanya menggunakan bootdisk yang penulis buat sendiri berbasis MS-DOS 6.22 karena Microsoft Windows 3.x tidak membutuhkan versi DOS yang spesifik seperti Microsoft Windows 9X. Pada bootdisk ini penulis isi dengan system DOS minimalis, disertai driver CD-ROM, partition manager dan program recovery untuk mengembalikan berkas yang terhapus, baik di disket maupun HDD. Didalam ISO CD juga penulis sertakan image dari bootdisk yang digunakan booting pada CD, sehingga apabila komputer anda tidak mendukung boot dari CD, maka bisa boot menggunakan disket 1.44MB.

Sebelum memasang Microsoft Windows 3.x ini, pastikan partisi HDD anda sudah terisi MS-DOS dan menggunakan filesystem FAT16! Bila HDD anda belum terpartisi, maka gunakan program partisi part244.exe pada image disket. Bila partisi anda belum terisi MS-DOS, maka lakukan format dengan menjalankan perintah "format c:/s/q" dimana c: adalah partisi bootable HDD anda.

Bila HDD anda sudah siap untuk dipasangi Microsoft Windows 3.x dan komputer anda mendukung booting dari CD, maka set booting pertama kali komputer anda pada CD. Masukkan CD kedalam drive CD-ROM, kemudian restart komputer anda. Maka tampilan pertama boot dari CD seperti gambar dibawah ini:

Tampilan Menu Dari Boot CD/Disk Untuk Memilih Versi Windows 3.x
Pilih versi Microsoft Windows 3.x yang akan anda pasang, kemudian tekan tombol enter, bila berhasil, maka program Setup dari Microsoft Windows 3.x akan terpanggil secara otomatis. Ikuti langkah-langkah yang ditampilkan oleh Setup untuk memasang Microsoft Windows 3.x ini.

Tampilan Setup Dari Microsoft Windows 3.00a

Sebagai bukti bahwa Microsoft Windows 3.x sukses terpasang, dapat dilihat pada gambar dibawah ini:
Bukti Microsoft Windows 3.0 Terpasang Dengan Baik

Bukti Microsoft Windows 3.00a Terpasang Dengan Baik

Bukti Microsoft Windows 3.1 Terpasang Dengan Baik

Bukti Microsoft Windows 3.1 for Workgroups Terpasang Dengan Baik

Bukti Microsoft Windows 3.11 Terpasang Dengan Baik

Bukti Microsoft Windows 3.11 for Workgroups Terpasang Dengan Baik
Microsoft Windows 3.x AIO ISO ini bisa diunduh disini. Selamat bernostalgia kembali dengan OS Microsoft Windows 3.x ini...

Selasa, 03 Desember 2019

Deteksi Plagiasi Pada Naskah Jurnal, Tesis, dan lain-lain

Pembaruan: 03-12-2019 
Karena tautan pada oload.stream habis masa berlakunya, maka penulis menaruh kembali program Plagiarism Detector versi 1092 serta Plagiarism Checker X versi 6.0.11 di Google Drive.

Pernahkah anda sekalian mendengar kata-kata 'PLAGIAT'? Kalau mendengar kata-kata itu solah-olah kita seperti merasa bersalah mencuri atau meniru hasil karya orang lain. Kenapa saya mem-posting tulisan ini? Karena saya mendapat tugas dari kantor untuk melakukan pengecekan tentang naskah untuk akreditasi.

Nah, saat ini ada program komputer yang menjadi andalan dalam pengecekan plagiasi pada suatu naskah, yaitu Plagiarism Detector versi 1092 dan Plagiarism Checker X versi 6.0.11. Pengecekan ini dapat secara on-line (tersambung internet) maupun secara off-line (berdasakan naskah-naskah yang ada dikomputer anda). Untuk hasil yang lebih akurat, sebaiknya pengecekan plagiasi dilakukan secara on-line saja.

Program aplikasi Plagiarism Detector versi 1092 ini juga digunakan oleh kampus-kampus ternama di Indonesia (sebagai contoh di Pascasarjana Universitas Brawijaya) untuk pengecekan plagiat bagi para mahasiswa yang akan submit (mengirimkan) naskah berupa paper, jurnal, thesis maupun disertasi

Tampilan awal aplikasi Plagiarism Detector 1092
Cara memasang program ini sebagai berikut:

1. Unduh aplikasi Plagiarism Detector 1092.
2. Buka file kompresi Plagiarism_Detector_v1092.zip di harddisk anda.
3. Jalankan file Plagiarism-Detector-Setup-1092.exe, ikuti langkah demi langkah sampai aplikasi tersebut terpasang dan aplikasi tersebut jangan dijalankan terlebih dahulu.
4. Salin dan timpa file Plagiarism Detector.exe dari hasil pembukaan kompresi tadi ke folder dimana aplikasi tersebut terpasang.
5. Jalankan aplikasi tersebut, akan muncul tulisan Plagiarism Detector Pro pada Active License Detail-nya.

Tampilan Plagiarism Detector sewaktu proses pengecekan plagiasi on-line
Selamat mencoba untuk mengecek naskah karya anda, apakah terkena plagiasi atau tidak.. Kedua aplikasi ini dapat diunduh disini (Plagiarism Detector versi 1092) dan disini (Plagiarism Checker X versi 6.0.11).

Rabu, 27 November 2019

Microsoft Windows 9X AIO (All-In-One)

Pada kesempatan ini, penulis akan membahas tentang sistem operasi Microsoft Windows 9X, yaitu OS Windows yang berbasis dari Windows 95. Secara tidak sengaja, penulis menemukan berkas ISO Windows 9X AIO yang pernah penulis buat di tahun sekitar 2010-an di HDD komputer lama.

Windows 9X AIO ini sudah bootable, tetapi penulis waktu itu masih "belum" berpengalaman sehingga proses memasang Windows 9X ini harus menjalankan berkas setup.exe secara manual setelah CD selesai booting. Kemarin penulis "membongkar" kembali ISO Windows 9X AIO ini, dan mengubah bootable CD menggunakan ISOLINUX dan MEMDISK agar bisa mem-boot CD dan memilih versi Windows yang akan dipasang.

Pertama-tama, penulis memperbarui bootable information di ISO menggunakan ISOLINUX.BIN agar CD nantinya dapat booting dan memuat menu untuk memilih versi Windows yang akan dipasang. Serta memasukkan bootdisk tiap versi Windows agar ketika memilih versi Windows yang akan dipasang, maka bootdisk Windows tersebut yang akan booting. Pilihan menu bootdisk disimpan pada file ISOLINUX.CFG.

Tampilan Menu Bootlader Untuk Memilih Versi Windows 9X
Setelah menu bootloader sudah dibuat dengan sukses, saatnya membuat bootdisk agar ketika salah satu versi Windows dipilih, maka secara otomatis setelah proses booting, maka setup Windows akan dijalankan secara otomatis. Ketika bootdisk telah dibuat, ternyata bootdisk tidak dapat menjalankan  setup Windows. Setelah ditelusui, ternyata untuk menemukan keberadaan CD Drive, bootdisk menggunakan berkas FINDCD.EXE dimana berkas ini akan mengecek keberadaan berkas SETUP.EXE di dalam folder folder \WIN95 (untuk Windows 95) \WIN98 (untuk Windows 98), dan \WIN9X (untuk Windows Me). Akhirnya penulis menggunakan Hex Editor, mengganti string :\WIN95\SETUP.EXE dengan :\README.TXT agar berkas FINDCD.EXE mengecek keberadaan berkas README.TXT di root folder dari CD Drive dan menimpa berkas FINDCD.EXE ditiap bootdisk dengan berkas yang baru ini.

Mengubah Isi Berkas FINDCD.EXE Agar Mengecek Adanya Berkas README.TXT
Selanjutnya adalah menyunting berkas AUTOEXEC.BAT ditiap bootdisk agar menjalankan berkas OEMSETUP.EXE sesuai dengan pilihan versi Windows yang akan dipasang. Baris perintah yang diganti adalah cd \WIN95 menjadi cd \WIN95A (sesuaikan dengan path versi Windows-nya).

Struktur Isi ISO CD Windows 9X AIO
Langkah selanjutnya adalah menambahkan file MSBATCH.INF untuk melewati proses pemasukan CD Product Key. Buat file MSBATCH.INF dan isikan baris dibawah ini selanjutnya simpan dan taruh ditiap folder versi Windows.

[Setup]
ProductType=1


Setelah itu, penulis coba ISO CD ini ke Virtual Machine VMware Workstation untuk melihat apakah usaha yang telah penulis lakukan membuahkan hasil.

Akhirnya Tampilan Setup Windows 95 Muncul Juga
Voila, akhirnya usaha yang dilakukan penulis berhasil!!! Selanjutnya tinggal menjalankan proses pemasangan dengan mengikuti petunjuk yang ditampilkan di Setup.

Bukti Bahwa Windows 95 B (OSR 2) Berhasil Terpasang
Windows 9X AIO ISO ini bisa diunduh disini. Selamat bernostalgia kembali dengan OS Microsoft Windows 9X ini...

Kamis, 10 Oktober 2019

Unboxing dan Review TV LED 32" Polytron Soundbar (PLD 32B1550)

Ketika penulis pulang ke rumah orangtua di Surabaya, penulis pernah berjanji untuk membelikan TV 32" untuk mengganti TV tabung orangtua yang sudah mati suaranya. Memilih TV LED tidaklah gampang, karena merek, kualitas dan harga menjadi faktor terpenting dalam memutuskan. Pilihan penulis jatuh ke TV LED merek Polytron, karena iklan TV LED Soundbar-nya yang gencar di televisi serta secara pribadi penulis, Polytron adalah merek dalam negeri yang sudah bermain lama di bidang audio dan rata-rata kualitas speaker untuk Bass sangatlah bagus, karena kakak penulis pernah mempunyai tape Bassoke dari Polytron dan kualitas bass-nya sangatlah bagus untuk ukuran tape saat itu.

Akhirnya penulis membeli TV LED Polytron Soundbar 32" (PLD 32B1550) karena harganya yang bersaing dengan merek lainnya (Rp. 2.099.000 di Hartono Electronic di Surabaya). Sebelum membeli, penulis mendengarkan dahulu kualitas dari soundbar di booth Polytron dan hasilnya sangatlah bagus. Sesampainya dirumah, penulis langsung unboxing dan me-review TV Polytron ini.

Box Terbagi Dua, Yaitu Untuk TV & Soundbar Serta Subwoofer
TV ini terbagi menjadi dua dus, yaitu dus pertama berisi TV LED 32" serta Soundbar-nya, sedangkan dus kedua berisi hanya Subwoofer-nya saja.

Isi Dari Box Adalah TV LED 32", Soundbar, Subwoofer, Kabel Input, Remote dan Kartu Garansi
Setelah isi dari kedua dus dikeluarkan, isinya adalah: TV LED 32", Soundbar, Subwoofer, Kabel male jack input 3.5mm ke RCA female untuk Soundbar, Remote dan Kartu Garansi.

Colokan RCA Untuk Soundbar, Colokan Mini Untuk Subwoofer
TV LED 32" ini TIDAK MEMILIKI SPEAKER INTERNAL jadi suara secara murni dikeluarkan ke Soundbar dan Subwoofer-nya. Soundbar dan Subwoofer-nya PASIF karena tidak memiliki power supply didalamnya. Jadi, kalau mau menggunakan Soundbar dan Subwoofer-nya secara terpisah (standalone) harus disambungkan dengan power amplifier serta jack dari subwoofer harus diganti dengan jack RCA atau dibiarkan dalam bentuk kabel.

TV Polytron Soundbar Sudah Terpasang
Secara keseluruhan unjuk kerja Soundbar dan Subwoofer sangat-sangat bagus, menurut penulis RECOMMENDED untuk dibeli. Untuk kualitas suara antara bass dan treble seimbang, bahkan subwoofer-nya menurut penulis responsif, nonton pilem maupun berita seolah-olah seperti nonton di dalam bioskop kecil hehehe... Kekurangan dari seri TV LED 32" ini adalah ukuran dari subwoofer-nya lebih kecil (sekitar 30x30cm) sedangkan untuk yang 40" keatas ukurannya lebih besar (sekitar 40x40cm). Resolusi layar untuk ukuran 32" masih HD (1366x768), bahkan yang ukuran 40" juga masih HD.

Demikian review singkat dari penulis tentang TV LED 32" Polytron Soundbar ini, semoga bermanfaat bagi anda yang masih penasaran dengan kualitas dari produk ini...

Rabu, 09 Oktober 2019

Upgrade Prosesor Komputer HP 8100 Elite SFF ke Xeon X3470 2.9 GHz

Sewaktu penulis berselancar di AliExpress, penulis teringat untuk mencari upgrade-an prosesor komputer meja di rumah orangtua penulis, yaitu HP 8100 Elite SFF yang masih menggunakan prosesor bawaan aslinya, yaitu Intel Core i5 650 (3.4 GHz). Sebenarnya prosesor ini sudah mumpuni untuk tugas sederhana, tapi tidak ada salahnya di-upgrade ke prosesor yang lebih tinggi. Ketika penulis masuk ke website HP, ditemukan bahwa komputer ini bisa di-upgrade prosesornya sampai dengan Intel Core i7 870.

Jenis Prosesor Yang Didukung Oleh HP 8100 Elite SFF
Ketika penulis mencari-cari prosesor Intel Core i5 750 maupun Intel Core i7 870, muncullah prosesor Intel Xeon X3470 2.93 GHz dimana harga prosesor ini setara dengan Intel Core i5 760 tetapi dengan kinerja yang menyamai Intel Core i7 870 (sama-sama 2.93 GHz). Kemudian penulis mencari info tambahan, apakah komputer HP 8100 Elite SSF ini mendukung jenis prosesor Xeon tersebut. Ternyata di forum-forum luar negeri menyatakan bahwa komputer tersebut mendukung jenis prosesor Xeon, bahkan ada yang mengunggah hasil benchmark-nya di beberapa situs benchmark terkenal.

Spesifikasi Prosesor Intel Xeon X3470 Dari Website Resmi Intel
Tanggal 1 September 2019 kemarin, penulis nekat memesan prosesor Intel Xeon X3470 tersebut di AliExpress dengan harga Rp. 224.653,- dibandingkan ditoko online Indonesia yag harganya melejit diatas Rp. 350.000,-. Setelah menunggu sekian lama, akhirnya prosesor ini sampai ditangan penulis pada tanggal 25 September 2019. Penulis baru bisa mencoba prosesor ini di komputer HP 8100 Elite SFF tersebut pada tanggal 9 Oktober 2019.

Prosesor Asli Komputer HP 8100 Elite SFF, Core i5 650

Prosesor HP 8100 Elite SFF Dengan Xeon X3470
Ketika prosesor sudah diganti, kemudian komputer dinyalakan, maka komputer akan menyala sebentar kemudian mati lagi tanpa ada tampilan apapun dilayar. Awalnya penulis kaget, apa prosesor ini tidak didukung oleh komputer ini, ternyata setelah di dinyalakan kembali, komputer menyala dengan normal. Ternyata komputer hidup sebentar kemudian mati lagi itu sedang mendeteksi prosesor baru yang terpasang kemudian memperbarui data prosesor tersebut di data BIOS.

Prosesor Terdeteksi di PC Info Windows 8.1 Enterprise
 
Prosesor Terdeteksi di DirectX Windows 8.1 Enterprise
Jangan takut mencoba mengganti prosesor komputer anda dengan prosesor yang tidak tertera secara official dari pabrikan komputer anda, asalkan anda mau mencari referensi di forum-forum luar negeri tentang penggantian prosesor tersebut di komputer yang sama seperti anda miliki.

Semoga tulisan ini bermanfaat bagi anda sekalian dalam mengganti prosesor untuk meningkatkan unjuk kerja komputer lama anda.

Rabu, 25 September 2019

Unboxing dan Review Speaker Robot RS170

Suatu hari penulis melihat-lihat speaker di Shopee dan penulis tertarik dengan speaker merek ROBOT tipe RS170. Harga murah, bentuk keren karena ada subwoofer-nya dengan harga termurah di Rp. 63.xxx,- disalah satu lapak Shopee. Penulis mencoba mencari review tentang speaker ini, tetapi penulis tidak menemukan sama sekali. Penulis hanya membaca review dari pembeli di Shopee maupun di Lazada yang mengatakan bahwa speaker ini layak dibeli.

Wel, akhirnya penulis pun tertarik membelinya karena harga juga murah, dan waktu itu ada pengembalian dana sebesar Rp. 63.xxx,- juga dari salah satu seller di Shopee karena stok barang tidak ada. Lumayan lah, tidak ada ruginya juga membeli speaker tersebut, itung-itung kalau suara jelek yaa memang dengan harga segitu masa mau dapat kualitas yang waah untuk sebuah speaker. Penulis pun membeli speaker tersebut beserta dengan tinta printer Canon dilapak yang sama.

Akhirnya, speaker pun tiba tanggal 25 September 2019 kemarin, langsung saja penulis unboxing sekalian me-review speaker ini.

Tampilan Box Speaker Robot RS170 Masih Tersegel
Speaker yang penulis terima masih tersegel rapi, berarti dari seller tidak dilakukan pengecekan sama sekali. Mungkin seller tidak ingin mengecewakan konsumen dengan tidak membuka segel (mungkin takut dibilang barang bekas hehehehe...).

Didalam Kotak Speaker Berisi Speaker, Kartu Petunjuk dan Kartu Garansi
Penulis langsung unboxing speaker ini, didalam kotak berisi speaker set yang dibungkus dengan bubble wrap, kartu petunjuk penggunaan serta kartu garansi. Di kartu garansi ini tertera tanggal produksi speaker ini, yaitu tertanggal 10 Mei 2019.

Tampilan Speaker Setelah Bubble Wrap Dibuka
Kemudian penulis langsung membuka bubble wrap dan inilah tampilan speaker aslinya. Bentuknya termasuk keren bagi penulis, mengingatkan bentuk speaker Sony warna maroon milik penulis yang dibeli sekitar 7 tahun yang lalu. Speaker ini bobotnya juga termasuk ringan lhoo, awalnya penulis tidak yakin dengan berat yang ringan ini, biasanya kalo bobot ringan itu berarti "kualitas" elektroniknya murahan!

Pengujian Speaker Dilaptop Menggunakan Lagu "Fly Away" Lenny Kravitz
Kemudian penulis langsung membawa speaker ini kedalam kamar untuk dilakukan pengujian suara menggunakan laptop, tancapkan kabel power ke USB port serta tancapkan jack 3.5mm ke output jack dilaptop. Langsung saja penulis memutar lagu "Fly Away"-nya Lenny Kravitz dan volume suara speaker dan laptop penulis putar dari terkecil hingga mentok. Selain itu, penulis juga menguji menggunakan lagu "Kamu Hoaxxx"-nya Boiyen dan "Zumbao"-nya Taboo.

Hasilnya? Bobot ringan itu berarti "kualitas" elektroniknya murahan itu tidak berlaku di speaker ini. Suara yang dihasilkan oleh speaker ini termasuk "Great" menurut penulis, karena dengan harga yang cuma Rp. 63.xxx,- suara yang dihasilkan termasuk mantabbb, terutama untuk bass tidak akan pecah meskipun volume dilaptop maupun dispeaker itu di mentokkan. Kerennya juga ada cahaya berwarna ungu di subwoofer-nya sehingga ada hiburan untuk melihat gerakan subwoofer ketika ada nada bass. Kekurangannya cuman satu, yaitu treble agak dominan daripada bass-nya sehingga kalau volume dibesarkan, maka treble lebih dominan tetapi tidak menutup keseluruhan dari suara bass-nya.

Cukup sekian review dari penulis tentang speaker Robot RS170 ini, semoga bermanfaat bagi anda yang punya budget minim tapi kepingin speaker maksi hehehe...

Kamis, 12 September 2019

Class FileUtils Untuk Mendapatkan File Real Path Pada Pemrograman Android

Ketika membuat aplikasi pada OS Android, kadang kala kita membutuhkan operasi baca dan tulis suatu berkas (file) di Androd. Penulis pernah menghadapi masalah ini, ketika mengambil suatu berkas, eh ternyata Android memberikan alamat path (alamat yang langsung menunjukkan letaknya) berkas tersebut dalam bentuk URI, bukan path langsung.

Setelah berselancar diinternet, akhirnya penulis mendapatkan fungsi FileUtils yang di-posting oleh Satyawan Hajare di alamat https://stackoverflow.com/questions/17546101/get-real-path-for-uri-android. Di forum Stack Overflow ini dijelaskan dengan detail cara penggunaan serta kode sumbernya. Tetapi tidak ada salahnya penulis juga reposting kode sumber tersebut disini, berikut ini kode sumber FileUtils.java :

1:  import android.annotation.SuppressLint;  
2:  import android.content.ContentUris;  
3:  import android.content.Context;  
4:  import android.database.Cursor;  
5:  import android.net.Uri;  
6:  import android.os.Build;  
7:  import android.os.Environment;  
8:  import android.provider.DocumentsContract;  
9:  import android.provider.MediaStore;  
10:  import android.provider.OpenableColumns;  
11:  import android.text.TextUtils;  
12:  import android.util.Log;  
13:  import java.io.File;  
14:  import java.io.FileOutputStream;  
15:  import java.io.InputStream;  
16:  import java.util.List;  
17:  public class FileUtils {  
18:    private static Uri contentUri = null;  
19:    /**  
20:     * Get a file path from a Uri. This will get the the path for Storage Access  
21:     * Framework Documents, as well as the _data field for the MediaStore and  
22:     * other file-based ContentProviders.<br>  
23:     * <br>  
24:     * Callers should check whether the path is local before assuming it  
25:     * represents a local file.  
26:     *  
27:     * @param context The context.  
28:     * @param uri   The Uri to query.  
29:     */  
30:    @SuppressLint("NewApi")  
31:    public static String getPath(final Context context, final Uri uri) {  
32:      // check here to KITKAT or new version  
33:      final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;  
34:      String selection = null;  
35:      String[] selectionArgs = null;  
36:      // DocumentProvider  
37:      if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {  
38:        // ExternalStorageProvider  
39:        if (isExternalStorageDocument(uri)) {  
40:          final String docId = DocumentsContract.getDocumentId(uri);  
41:          final String[] split = docId.split(":");  
42:          final String type = split[0];  
43:          String fullPath = getPathFromExtSD(split);  
44:          if (fullPath != "") {  
45:            return fullPath;  
46:          } else {  
47:            return null;  
48:          }  
49:        }  
50:        // DownloadsProvider  
51:        else if (isDownloadsDocument(uri)) {  
52:          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {  
53:            final String id;  
54:            Cursor cursor = null;  
55:            try {  
56:              cursor = context.getContentResolver().query(uri, new String[]{MediaStore.MediaColumns.DISPLAY_NAME}, null, null, null);  
57:              if (cursor != null && cursor.moveToFirst()) {  
58:                String fileName = cursor.getString(0);  
59:                String path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName;  
60:                if (!TextUtils.isEmpty(path)) {  
61:                  return path;  
62:                }  
63:              }  
64:            } finally {  
65:              if (cursor != null)  
66:                cursor.close();  
67:            }  
68:            id = DocumentsContract.getDocumentId(uri);  
69:            if (!TextUtils.isEmpty(id)) {  
70:              if (id.startsWith("raw:")) {  
71:                return id.replaceFirst("raw:", "");  
72:              }  
73:              String[] contentUriPrefixesToTry = new String[]{  
74:                  "content://downloads/public_downloads",  
75:                  "content://downloads/my_downloads"  
76:              };  
77:              for (String contentUriPrefix : contentUriPrefixesToTry) {  
78:                try {  
79:                  final Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));  
80:                  return getDataColumn(context, contentUri, null, null);  
81:                } catch (NumberFormatException e) {  
82:                  //In Android 8 and Android P the id is not a number  
83:                  return uri.getPath().replaceFirst("^/document/raw:", "").replaceFirst("^raw:", "");  
84:                }  
85:              }  
86:            }  
87:          } else {  
88:            final String id = DocumentsContract.getDocumentId(uri);  
89:            //final boolean isOreo = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;  
90:            if (id.startsWith("raw:")) {  
91:              return id.replaceFirst("raw:", "");  
92:            }  
93:            try {  
94:              contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));  
95:            } catch (NumberFormatException e) {  
96:              e.printStackTrace();  
97:            }  
98:            if (contentUri != null) {  
99:              return getDataColumn(context, contentUri, null, null);  
100:            }  
101:          }  
102:        }  
103:        // MediaProvider  
104:        else if (isMediaDocument(uri)) {  
105:          final String docId = DocumentsContract.getDocumentId(uri);  
106:          final String[] split = docId.split(":");  
107:          final String type = split[0];  
108:          Uri contentUri = null;  
109:          if ("image".equals(type)) {  
110:            contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;  
111:          } else if ("video".equals(type)) {  
112:            contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;  
113:          } else if ("audio".equals(type)) {  
114:            contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;  
115:          }  
116:          selection = "_id=?";  
117:          selectionArgs = new String[]{split[1]};  
118:          return getDataColumn(context, contentUri, selection, selectionArgs);  
119:        } else if (isGoogleDriveUri(uri)) {  
120:          return getDriveFilePath(uri, context);  
121:        }  
122:      }  
123:      // MediaStore (and general)  
124:      else if ("content".equalsIgnoreCase(uri.getScheme())) {  
125:        if (isGooglePhotosUri(uri)) {  
126:          return uri.getLastPathSegment();  
127:        }  
128:        if (isGoogleDriveUri(uri)) {  
129:          return getDriveFilePath(uri, context);  
130:        }  
131:        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N) {  
132:          // return getFilePathFromURI(context,uri);  
133:          return getMediaFilePathForN(uri, context);  
134:          // return getRealPathFromURI(context,uri);  
135:        } else {  
136:          return getDataColumn(context, uri, null, null);  
137:        }  
138:      }  
139:      // File  
140:      else if ("file".equalsIgnoreCase(uri.getScheme())) {  
141:        return uri.getPath();  
142:      }  
143:      return null;  
144:    }  
145:    /**  
146:     * Check if a file exists on device  
147:     *  
148:     * @param filePath The absolute file path  
149:     */  
150:    private static boolean fileExists(String filePath) {  
151:      File file = new File(filePath);  
152:      return file.exists();  
153:    }  
154:    /**  
155:     * Get full file path from external storage  
156:     *  
157:     * @param pathData The storage type and the relative path  
158:     */  
159:    private static String getPathFromExtSD(String[] pathData) {  
160:      final String type = pathData[0];  
161:      final String relativePath = "/" + pathData[1];  
162:      String fullPath = "";  
163:      // on my Sony devices (4.4.4 & 5.1.1), `type` is a dynamic string  
164:      // something like "71F8-2C0A", some kind of unique id per storage  
165:      // don't know any API that can get the root path of that storage based on its id.  
166:      //  
167:      // so no "primary" type, but let the check here for other devices  
168:      if ("primary".equalsIgnoreCase(type)) {  
169:        fullPath = Environment.getExternalStorageDirectory() + relativePath;  
170:        if (fileExists(fullPath)) {  
171:          return fullPath;  
172:        }  
173:      }  
174:      // Environment.isExternalStorageRemovable() is `true` for external and internal storage  
175:      // so we cannot relay on it.  
176:      //  
177:      // instead, for each possible path, check if file exists  
178:      // we'll start with secondary storage as this could be our (physically) removable sd card  
179:      fullPath = System.getenv("SECONDARY_STORAGE") + relativePath;  
180:      if (fileExists(fullPath)) {  
181:        return fullPath;  
182:      }  
183:      fullPath = System.getenv("EXTERNAL_STORAGE") + relativePath;  
184:      if (fileExists(fullPath)) {  
185:        return fullPath;  
186:      }  
187:      return fullPath;  
188:    }  
189:    private static String getDriveFilePath(Uri uri, Context context) {  
190:      Uri returnUri = uri;  
191:      Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);  
192:      /*  
193:       * Get the column indexes of the data in the Cursor,  
194:       *   * move to the first row in the Cursor, get the data,  
195:       *   * and display it.  
196:       * */  
197:      int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);  
198:      int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);  
199:      returnCursor.moveToFirst();  
200:      String name = (returnCursor.getString(nameIndex));  
201:      String size = (Long.toString(returnCursor.getLong(sizeIndex)));  
202:      File file = new File(context.getCacheDir(), name);  
203:      try {  
204:        InputStream inputStream = context.getContentResolver().openInputStream(uri);  
205:        FileOutputStream outputStream = new FileOutputStream(file);  
206:        int read = 0;  
207:        int maxBufferSize = 1 * 1024 * 1024;  
208:        int bytesAvailable = inputStream.available();  
209:        //int bufferSize = 1024;  
210:        int bufferSize = Math.min(bytesAvailable, maxBufferSize);  
211:        final byte[] buffers = new byte[bufferSize];  
212:        while ((read = inputStream.read(buffers)) != -1) {  
213:          outputStream.write(buffers, 0, read);  
214:        }  
215:        Log.e("File Size", "Size " + file.length());  
216:        inputStream.close();  
217:        outputStream.close();  
218:        Log.e("File Path", "Path " + file.getPath());  
219:        Log.e("File Size", "Size " + file.length());  
220:      } catch (Exception e) {  
221:        Log.e("Exception", e.getMessage());  
222:      }  
223:      return file.getPath();  
224:    }  
225:    private static String getMediaFilePathForN(Uri uri, Context context) {  
226:      Uri returnUri = uri;  
227:      Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);  
228:      /*  
229:       * Get the column indexes of the data in the Cursor,  
230:       *   * move to the first row in the Cursor, get the data,  
231:       *   * and display it.  
232:       * */  
233:      int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);  
234:      int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);  
235:      returnCursor.moveToFirst();  
236:      String name = (returnCursor.getString(nameIndex));  
237:      String size = (Long.toString(returnCursor.getLong(sizeIndex)));  
238:      File file = new File(context.getFilesDir(), name);  
239:      try {  
240:        InputStream inputStream = context.getContentResolver().openInputStream(uri);  
241:        FileOutputStream outputStream = new FileOutputStream(file);  
242:        int read = 0;  
243:        int maxBufferSize = 1 * 1024 * 1024;  
244:        int bytesAvailable = inputStream.available();  
245:        //int bufferSize = 1024;  
246:        int bufferSize = Math.min(bytesAvailable, maxBufferSize);  
247:        final byte[] buffers = new byte[bufferSize];  
248:        while ((read = inputStream.read(buffers)) != -1) {  
249:          outputStream.write(buffers, 0, read);  
250:        }  
251:        Log.e("File Size", "Size " + file.length());  
252:        inputStream.close();  
253:        outputStream.close();  
254:        Log.e("File Path", "Path " + file.getPath());  
255:        Log.e("File Size", "Size " + file.length());  
256:      } catch (Exception e) {  
257:        Log.e("Exception", e.getMessage());  
258:      }  
259:      return file.getPath();  
260:    }  
261:    private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {  
262:      Cursor cursor = null;  
263:      final String column = "_data";  
264:      final String[] projection = {column};  
265:      try {  
266:        cursor = context.getContentResolver().query(uri, projection,  
267:            selection, selectionArgs, null);  
268:        if (cursor != null && cursor.moveToFirst()) {  
269:          final int index = cursor.getColumnIndexOrThrow(column);  
270:          return cursor.getString(index);  
271:        }  
272:      } finally {  
273:        if (cursor != null)  
274:          cursor.close();  
275:      }  
276:      return null;  
277:    }  
278:    /**  
279:     * @param uri - The Uri to check.  
280:     * @return - Whether the Uri authority is ExternalStorageProvider.  
281:     */  
282:    private static boolean isExternalStorageDocument(Uri uri) {  
283:      return "com.android.externalstorage.documents".equals(uri.getAuthority());  
284:    }  
285:    /**  
286:     * @param uri - The Uri to check.  
287:     * @return - Whether the Uri authority is DownloadsProvider.  
288:     */  
289:    private static boolean isDownloadsDocument(Uri uri) {  
290:      return "com.android.providers.downloads.documents".equals(uri.getAuthority());  
291:    }  
292:    /**  
293:     * @param uri - The Uri to check.  
294:     * @return - Whether the Uri authority is MediaProvider.  
295:     */  
296:    private static boolean isMediaDocument(Uri uri) {  
297:      return "com.android.providers.media.documents".equals(uri.getAuthority());  
298:    }  
299:    /**  
300:     * @param uri - The Uri to check.  
301:     * @return - Whether the Uri authority is Google Photos.  
302:     */  
303:    private static boolean isGooglePhotosUri(Uri uri) {  
304:      return "com.google.android.apps.photos.content".equals(uri.getAuthority());  
305:    }  
306:    /**  
307:     * @param uri The Uri to check.  
308:     * @return Whether the Uri authority is Google Drive.  
309:     */  
310:    private static boolean isGoogleDriveUri(Uri uri) {  
311:      return "com.google.android.apps.docs.storage".equals(uri.getAuthority()) || "com.google.android.apps.docs.storage.legacy".equals(uri.getAuthority());  
312:    }  
313:  }  

Cara penggunaan class FileUtils sebagai berikut:

 /* Untuk menyimpan lokasi file yang dipilih */  
 Uri pilihFile=null;  
 /* Untuk menyimpan nama file dan path nya */  
 String pathFile;  
   
 // Ambil Uri file  
 pilihFile = data.getData();  
 // Cek, apakah isi pilihFile berisi Uri?  
 if (pilihFile != null) {  
   // Jika keduanya YA , kerjakan perintah berikut ini:  
   
   /* Panggil class FileUtils untuk mendapatkan path dari berkas yang akan digunakan dan  
      simpan hasilnya di variabel pathFile */  
   pathFile = FileUtils.getPath(getActivity(),pilihFile);  
 }  

Selamat menggunakan class FileUtil ini diprogram Android buatan anda sendiri...

Jumat, 06 September 2019

Pemrograman Aplikasi Tab Swipeable View Seperti Aplikasi WhatsApp

Pada saat penulis membuat tesis S2, yaitu membuat suatu program steganografi, penulis sangat tertarik dengan model aplikasi WhatsApp, dimana aplikasi ini menggunakan beberapa Tabs untuk memisahkan fungsinya. Serta pengguna dapat melakukan swipe (menggeser pada layar) untuk berpindah antar halaman pada Tabs tersebut.

Penulis berburu beberapa kode pada internet, banyak yang beredar cara-cara membuat aplikasi yang "mirip" dengan WhatsApp, ada beberapa kode yang berjalan dengan baik di emulator Android SDK tetapi tidak dapat berjalan di emulator maupun ponsel Android. Ada beberapa kode yang mencontohkan, tetapi tidak menjelaskan bagaimana cara menambahkan suatu TextEdit, Button, dll pada halaman pada Tabs tersebut, hanya tampilanTabs saja. Akhirnya penulis menemukan tutorial kode "Tab Layout with Swipeable View Using Fragments in Android App" di alamat blog http://androidminess.blogspot.com/2016/01/android-tab-layout-with-swipeable-view.html. Penulis mengikuti cara yang dijelaskan pada blog tersebut, tetapi ketika di Generate APK di Android SDK ternyata banyak terjadi kesalahan. Akhirnya penulis menelusuri secara perlahan-lahan untuk mengetahui cara kerja dari kode program tersebut dan akhirnya penulis berhasil mengkoreksi kode di MainActivity.java serta strings.xml, karena di kedua file tersebut terjadi kesalahan dalam memanggil reference string.

Tampilan Tab Swipeable View Yang Diperbaiki dan Dirubah Penulis

Tampilan Menu Pada Tab Swipeable View

Usut punya usut, ternyata cara kerja Tabs pada aplikasi WhatApps adalah menggunakan Fragment, yaitu "memecah" layar "utama" menjadi beberapa halaman, sehingga halaman-halaman tersebut bisa ditampilkan pada layar "utama" bila Tabs tersebut dipilih.

Untuk mengubah jumlah fragment dapat dilakukan di berkas SectionPagerAdapter.java di baris kode berikut:

  @Override  
   public int getCount() {  
     // Show 3 total pages.  
     return 3; <- ganti dengan jumlah fragment yang diinginkan  
   }  
   
 untuk mengganti nama Tabs dilakukan pada baris kode berikut:  
   
 @Override  
   public CharSequence getPageTitle(int position) {  
     String tabName="";  
     switch (position) {  
       // Nama-nama Tiap TABS disini  
       case 0:  
         tabName = mContext.getResources().getString(R.string.app_tab1);  
         return tabName; <- ganti dengan nama Tabs yang diinginkan  
         // return "STEGO";  
       case 1:  
         tabName = mContext.getResources().getString(R.string.app_tab2);  
         return tabName; <- ganti dengan nama Tabs yang diinginkan  
         //return "CHAT";  
       case 2:  
         tabName = mContext.getResources().getString(R.string.app_tab3);  
         return tabName; <- ganti dengan nama Tabs yang diinginkan  
         //return "SETTINGS";  
     }  
     return null;  
   }  
   
 Untuk menampilkan isi halaman pada fragment dapat dilakukan di berkas MainActivity.java pada baris kode berikut:  
   
 switch (getArguments().getInt(ARG_SECTION_NUMBER)) {  
         case 1:  
           viewFrag = inflater.inflate(R.layout.frag_stego, container, false); <- ganti dengan nama berkas fragment .xml yang akan ditampilkan  
           textView = (TextView) viewFrag.findViewById(R.id.stego_label);  
           textView.setText(getString(R.string.app_tab1)+" "+  
           getArguments().getInt(ARG_SECTION_NUMBER));  
           return viewFrag;  
         case 2:  
           viewFrag = inflater.inflate(R.layout.frag_chat, container, false); <- ganti dengan nama berkas fragment .xml yang akan ditampilkan  
           textView = (TextView) viewFrag.findViewById(R.id.chat_label);  
           textView.setText(getString(R.string.app_tab2)+" "+  
           getArguments().getInt(ARG_SECTION_NUMBER));  
           return viewFrag;  
         case 3:  
           viewFrag = inflater.inflate(R.layout.frag_settings, container, false); <- ganti dengan nama berkas fragment .xml yang akan ditampilkan  
           textView = (TextView) viewFrag.findViewById(R.id.settings_label);  
           textView.setText(getString(R.string.app_tab3)+" "+  
           getArguments().getInt(ARG_SECTION_NUMBER));  
           return viewFrag;  
       }  
       return null;  

Kode sumber program ini dapat diunduh disini. Silahkan dicoba dan galilah kreasi anda dalam mengembangkan aplikasi Android.

Happy programming!!!

Senin, 12 Agustus 2019

Mengganti Power Supply Dekoder Parabola Philsat Neymar HD

Dekoder parabola Philsat Neymar HD PL-101 milik penulis mengalami kerusakan pada power supply-nya, entah kenapa sebabnya, tiba-tiba saja sekitar 2 minggu yang lalu tidak mau menyala. Hanya ada tanda power dengan cahaya yang remang-remang.

Lampu power on menyala remang, tanda kerusakan power supply
Casing dekoder penulis bongkar, kemudian penulis melihat rangkaian power supply dan memesan rangkaian power supply yang cocok dan persis dengan yang ada di dekoder di Shopee.

Rangkaian power supply disebelah kiri, sebelah kanan rangkaian dekoder
Akhirnya ketemu dengan harga 35rb, dan yang jual tokonya di daerah Pamekasan Madura!

Rangkaian power supply yang baru

Atas power supply lama, bawah yang baru
Sebelum memasang power supply yang baru, HARAP PERHATIKAN tegangan output dari power supply yang baru (5.5V, G, 15V dan 20V) JANGAN SAMPAI TERBALIK ketika memasang ke rangkaian dekoder. Bila terbalik, akan fatal akibatnya, yaitu rangkaian dekoder bisa hangus! Tapi rangkaian power supply yang baru meskipun terlihat terbalik tegangan output-nya ternyata konektor untuk ke rangkaian dekoder sesuai dengan urutan rangkaian power supply aslinya.

Rangkaian power supply yang baru sudah terpasang di dekoder Philsat
Setelah rangkaian power supply terpasang, saatnya uji coba, yaitu coba menghidupkan dekoder tanpa harus tersambung ke antena parabola. Tinggal colokkan listrik, tekan tombol power untuk menghidupkan dekoder.

Akhirnya dekoder mau on juga, tandanya power supply baru bekerja dengan baik
Kini saatnya dekoder disambungkan dengan antena parabola dan televisi untuk mengecek apakah dekoder bekerja dengan baik.

Dekoder sudah bekerja nomal kembali, ditandai terdeteksinya tayangan channel
Akhirnya, dekoder Philsat Neymar HD PL-101 milik penulis kembali bekerja dengan normal kembali dan bisa menonton tayangan channel di parabola.

Semoga tulisan ini bermanfaat untuk para pembaca setia blog ini, agar dapat melakukan penggantian sendiri rangkaian power supply dekoder parabola yang rusak.

Rabu, 07 Agustus 2019

Cara Menggunakan MikroTik RouterOS

Penulis mendapatkan MikroTik RouterOS versi terbaru (6.47.4) dan mengunggahnya. Untuk mencoba versi terbaru MikroTik RouterOS ini, silahkan unduh disini.

Ditulis pada 07-08-2019
 
Pada kesempatan kali ini, penulis mendapatkan pelatihan MTCNA (MikroTik Certified Network Associate). Penulis teringat pernah mengunduh MikroTik RouterOS versi 6.34.3 yang sudah dijebol orang sehingga berlisensi Level 6, dimana lisensi ini merupakan tingkatan tertinggi dalam MikroTik.

RouterOS yang penulis unduh ini merupakan versi preinstalled di VMware Workstation, dan yang menjadi kendala adalah laptop Lenovo G50-45 milik penulis menggunakan prosesor AMD E1 tetapi anehnya ketika menggunakan VMware Workstation versi 15.1 (terbaru saat ini) ketika menjalankan virtual machine RouterOS, menampilkan pesan kesalahan bahwa fitur AMD-V virtualization tidak aktif. Padahal ketika penulis cek menggunakan aplikasi CPU-Z, fitur AMD-V ini didukung oleh prosesor AMD E1 ini tetapi sepertinya tidak diaktifkan oleh Lenovo, bahkan di menu BIOS tidak terdapat menu untuk mengaktifkan fitur AMD-V ini.

Setelah mencoba beberapa versi VMware Workstation yang penulis punya, ternyata VMware Workstation versi 8 sampai dengan 11 (dapat dunduh disini) merupakan yang paling ideal untuk menjalankan RouterOS, karena versi 8 ini tidak membutuhkan fitur Intel VT-X maupun AMD-V untuk menjalankan virtual machine. Serta versi ini juga mendukung format virtual machine yang digunakan oleh vendor MikroTik.

Tampilan RouterOS di VMware Workstation versi 8.0.4
Setelah berhasil menjalankan RouterOS di VMware Workstation, sekarang tinggal bagaimana caranya agar aplikasi Winbox dapat terhubung dengan RouterOS di VMware Workstation. Setelah berselancar di internet, akhirnya penulis mendapatkan caranya, yaitu sebagai berikut:

Setelan agar Winbox dapat terhubung dengan RouterOS di VMware
1. Matikan virtual machine RouterOS bila masih berjalan di VMware Workstation.
2. Klik menu Edit virtual machine settings.
3. Pada tab Hardware, klik Network Adapter.
4. Pada Network connection pilih Custom: Specific virtual network. Kemudian pada menu dropdown, pilih VMnet1 (Host-only). Kemudian klik Advanced...
5. Lihat pada baris MAC Address bila masih kosong, klik Generate kemudian salin alamat MAC tersebut.
6. Simpan setelan tersebut. Kemudian jalankan kembali virtual machine RouterOS.
7. Buka aplikasi Winbox, kemudian tempelkan (paste) ke baris Connect To:. Kemudian klik tab Neighbors, lihat dibagian kolom MAC Address, klik salah satu kemudian klik Connect untuk menyambungkan.

Cara menghubungkan Winbox ke RouterOS di VMware
8. Tunggu sebentar, maka Winbox akan terhubung ke RouterOS.  Maka anda sudah dapat menyetel RouterOS.

Winbox sudah terhubung MikroTik RouterOS di VMware

Untuk mematikan RouterOS, dapat dilakukan di virtual machine maupun melalui Winbox. Untuk mematikan RouterOS, di terminal console ketikkan system kemudian tekan tombol enter di keyboard, ketikkan lagi shutdown kemudian tekan tombol enter di keyboard, konfirmasi dengan menekan tombol y di keyboard untuk mematikan. Perintah ini juga dapat dirapel dengan cara mengetikkan system shutdown kemudian tekan tombol enter di keyboard, konfirmasi dengan menekan tombol y di keyboard untuk mematikan.

Untuk mencoba MikroTik RouterOS versi 6.34.3 ini maupun versi terbaru dapat diunduh disini.

Selamat mencoba!!!

Sabtu, 27 Juli 2019

Cara Membuka Casing Baterai Laptop Lenovo G50-45

Kembali lagi saya mengulas laptop kelas ekonomi saya (prosesor AMD E1), yaitu Lenovo G50-45. Kali ini membahas tentang mengganti baterai laptop ini yang sudah tidak mau dicas lagi kurang lebih 6 bulanan. Model baterai yang tertera pada casing baterai adalah L12L4E01 yang dapat digunakan di laptop Lenovo seri G40 dan G50. Awalnya malam minggu ini saya berniat untuk membuka casing baterai tersebut dengan cara menggerindanya menggunakan gerinda mini. Tetapi tanpa sengaja, pas saya putar-putar berlawanan arah antara bagian atas dan bawah baterai tiba-tiba casing baterai terbuka dengan sendirinya.

Untuk lebih jelasnya cara untuk membuka casing baterai ini, dapat dilihat di gambar-gambar dibawah ini:

Casing yang terbuka dengan cara dipuntir
1. Tahan bagian atas baterai dengan menggunakan tangan dan jempol kiri seperti gambar diatas, kemudian bagian bawah baterai tahan dengan tangan kanan. Putar tangan kiri kearah kanan dan putar tangan kanan kearah kiri (saling berlawanan arah), maka casing akan terbuka dengan sendirinya. Lakukan hal ini untuk membuka kedua sisi baterai.

Tahan dan buka casing dengan kedua tangan
2. Untuk membuka bagian tengah casing, gunakan kedua tangan seperti gambar diatas dan lakukan secara perlahan-lahan untuk membuka rata bagian tengah casing.

Casing baterai terbuka seluruhnya
Setelah terbuka, tinggal melepaskan baterai dari casing
3. Untuk melepaskan baterai dari casing-nya, lepas dahulu rangkaian charger dari casing kemudian balikkan casing (ditelungkupkan) kemudian cungkil baterai maka rangkaian baterai akan lepas dengan sendirinya.

Rangkaian charger dan baterai terlepas dari casing
Baterai yang digunakan jenis 18650 dengan kapasitas 2800mAh
4. Jenis baterai yang digunakan jenis 1860 dengan kapasitas 2800 mAh yang dirangkai secara seri (dapat dilihat di label casing tertulis 14.8V (4x3.7V = 14.8V) 2800 mAh. Ingat! Rangkaian seri itu menaikkan tegangan (voltase) tetapi arus tetap (mAh).
Untuk mengganti baterai dapat menggunakan baterai jenis 18650 flat top dengan kapasitas 2800 mAh atau lebih tinggi (agar lebih tahan lama).

Semoga tulisan ini bermanfaat bagi anda sekalian dalam membuka casing baterai laptop Lenovo. Cara ini juga dapat digunakan untuk membuka casing baterai laptop lainnya yang bentuknya juga sama. Selamat mencoba!