Jeff Fisher, tim Google Data API
Januari 2008
Pendahuluan: Cakupan Sampel
Download file yang dapat dieksekusi contoh.
Salah satu hal menarik tentang Documents List Data API adalah API ini memungkinkan developer membuat alat migrasi bagi pengguna yang masih beradaptasi dengan Google Dokumen. Untuk tujuan penggunaan API ini, saya telah menggunakan .NET Client Library untuk membuat aplikasi pengupload .NET 2.0, yang diberi judul "DocList Uploader". Anda bisa mendapatkan sumber uploader dari subversion.
Contoh ini dimaksudkan untuk memudahkan pengguna memigrasikan dokumen dari komputer ke Google Dokumen. Fitur ini memungkinkan pengguna login ke Akun Google mereka, lalu menarik lalu melepas file yang didukung yang kemudian diupload secara otomatis. Contoh ini juga memberikan opsi untuk menambahkan opsi menu klik kanan ke shell Windows Explorer untuk mengupload file. Contoh ini disediakan berdasarkan Lisensi Apache 2.0, sehingga Anda bebas menggunakannya sebagai titik awal untuk program Anda sendiri.
Artikel ini dimaksudkan untuk menunjukkan cara beberapa perilaku sampel dicapai menggunakan framework .NET. Sebagian besar terdiri dari cuplikan kode yang diberi anotasi dari bagian yang relevan. Artikel ini tidak membahas cara membuat formulir dan komponen UI lainnya dari aplikasi itu sendiri, karena ada banyak artikel Visual Studio yang membahasnya secara mendetail. Jika Anda ingin tahu cara komponen UI dikonfigurasi, Anda dapat memuat file project sendiri, dengan mendownload library klien dan melihat di dalam subdirektori "clients\cs\samples\DocListUploader".
Membuat Aplikasi Area Notifikasi
Alat migrasi biasanya dapat berjalan tanpa mengganggu di sistem operasi, memperluas kemampuan OS tanpa terlalu mengganggu pengguna. Salah satu cara untuk menyusun alat semacam itu di Windows adalah dengan membuatnya berjalan di luar area notifikasi, bukan memenuhi taskbar. Hal ini membuat pengguna lebih cenderung membiarkan program berjalan terus-menerus, bukan hanya membuka program saat mereka perlu melakukan tugas tertentu. Ini adalah ide yang sangat berguna untuk contoh ini karena tidak perlu menyimpan kredensial autentikasi ke disk.
Aplikasi area notifikasi adalah aplikasi yang berjalan terutama hanya dengan NotifyIcon di area notifikasi (area di dekat jam pada taskbar). Saat mendesain aplikasi semacam itu, ingatlah bahwa Anda tidak ingin formulir utama project menjadi formulir yang berinteraksi dengan pengguna. Sebagai gantinya, buat formulir terpisah untuk ditampilkan saat aplikasi dijalankan. Alasannya akan dijelaskan sebentar lagi.
Dalam contoh ini, saya telah membuat dua formulir: HiddenForm, formulir utama aplikasi dengan sebagian besar logika, dan OptionsForm, formulir yang memungkinkan pengguna menyesuaikan beberapa opsi dan login ke Akun Google mereka. Saya juga menambahkan NotifyIcon bernama DocListNotifyIcon ke HiddenForm dan menyesuaikannya dengan ikon saya sendiri. Untuk memastikan HiddenForm tidak dilihat oleh pengguna, saya menyetel opasitasnya ke 0%, WindowState ke Minimized, dan properti ShowInTaskbar ke False.
Biasanya, saat program kehabisan ruang di area notifikasi sistem, menutup aplikasi tidak akan menghentikan program, tetapi menyembunyikan semua formulir aktif dan hanya membuat NotifyIcon terlihat. Untuk melakukannya, kita harus mengganti peristiwa "FormClosing" formulir kita sebagai berikut:
private void OptionsForm_FormClosing(object sender, FormClosingEventArgs e)
{
if(e.CloseReason == CloseReason.UserClosing) {
this.Hide();
e.Cancel = true;
}
}Kita juga mungkin ingin menyembunyikan formulir saat pengguna meminimalkannya, karena tidak ada alasan untuk memakan ruang di taskbar karena kita sudah memiliki ikon notifikasi. Hal ini dapat dilakukan dengan cuplikan kode berikut:
private void OptionsForm_Resize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
this.Hide();
}
}Sekarang karena kita tidak mengizinkan pengguna menutup OptionsForm, kita dapat mempertahankan satu instance yang terikat ke HiddenForm. Saat ingin menampilkan OptionsForm lagi, kita cukup memanggil metode Show-nya.
Karena formulir utama aplikasi ini, HiddenForm, tidak terlihat oleh pengguna, kita harus memberi mereka cara untuk keluar dari aplikasi kita. Saya memilih untuk menambahkan ContextMenu ke NotifyIcon dengan ToolStripMenuItem untuk menutup aplikasi. Untuk menulis handler klik sangatlah mudah, cukup panggil metode Close HiddenForm.
Tips Balon
Banyak aplikasi area notifikasi berkomunikasi dengan pengguna dengan menampilkan balon tips, yang terlihat seperti balon bulat yang berasal dari NotifyIcon. Balon dapat ditampilkan sebagai berikut:
DocListNotifyIcon.ShowBalloonTip(10000, "Title", "Example Text", ToolTipIcon.Info);
Argumen pertama adalah jumlah waktu dalam milidetik untuk menampilkan balon. Perhatikan bahwa ada jumlah waktu minimum dan maksimum yang akan diizinkan OS untuk kolom ini, yaitu 10 dan 30 detik. Argumen kedua dan ketiga menentukan judul dan beberapa konten untuk balon. Argumen terakhir memungkinkan Anda memilih ikon untuk menggambarkan tujuan balon.
Mengupload Dokumen
Mengupload dokumen sangatlah mudah. Sebagian besar pekerjaan dilakukan oleh metode UploadDocument dari objek DocumentsService. Proses ini dijelaskan secara lebih jelas dalam Panduan Developer untuk Documents List API.
service = new DocumentsService("DocListUploader");
((GDataRequestFactory) service.RequestFactory).KeepAlive = false;
service.setUserCredentials(username, password);Pertama, objek DocumentsService harus diinisialisasi dan kredensial pengguna harus diberikan. Untuk mencegah beberapa masalah saat mengupload beberapa file, header HTTP "keep-alive" telah dinonaktifkan karena diketahui menyebabkan beberapa masalah dengan .NET Framework.
lastUploadEntry = service.UploadDocument(fileName, null);
Cuplikan ini mengupload file di jalur yang terdapat dalam string fileName. Argumen kedua yang berupa null menunjukkan bahwa nama file Google Dokumen harus sama dengan nama file asli.
Menangani Tarik lalu Lepas
Untuk mempermudah upload, sebaiknya izinkan pengguna menarik lalu melepas file dari folder mereka ke aplikasi untuk menguploadnya. Langkah pertama adalah mengizinkan operasi pelepasan dari file, kode di bawah akan mengubah kursor untuk menunjukkan bahwa pelepasan diizinkan:
private void OptionsForm_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
{
e.Effect = DragDropEffects.Copy;
}
}Setelah file atau grup file dilepas, kita harus menangani peristiwa tersebut dengan memeriksa setiap file yang dilepas dan menguploadnya:
private void OptionsForm_DragDrop(object sender, DragEventArgs e)
{
string[ fileList = (string[) e.Data.GetData(DataFormats.FileDrop);
foreach (string file in fileList)
{
mainForm.UploadFile(file);
}
}Mencantumkan Dokumen
Mendapatkan daftar dokumen dari server adalah cara yang baik untuk mengingatkan pengguna tentang dokumen yang telah mereka upload. Cuplikan di bawah menggunakan objek DocumentsService yang kita inisialisasi sebelumnya untuk mengambil semua dokumen dari server.
public DocumentsFeed GetDocs()
{
DocumentsListQuery query = new DocumentsListQuery();
DocumentsFeed feed = service.Query(query);
return feed;
}Cara mudah untuk memvisualisasikan data ini adalah dengan menggunakan ListView. Saya menambahkan ListView bernama DocList ke OptionsForm. Agar lebih bagus, saya juga membuat ImageList ikon kustom untuk mengilustrasikan berbagai jenis dokumen. Kode berikut mengisi ListView dengan informasi yang diambil dari feed di atas:
public void UpdateDocList()
{
DocList.Items.Clear();
DocumentsFeed feed = mainForm.GetDocs();
foreach (DocumentEntry entry in feed.Entries)
{
string imageKey = "";
if (entry.IsDocument)
{
imageKey = "Document.gif";
}
else if (entry.IsSpreadsheet)
{
imageKey = "Spreadsheet.gif";
}
else
{
imageKey = "Presentation.gif";
}
ListViewItem item = new ListViewItem(entry.Title.Text, imageKey);
item.SubItems.Add(entry.Updated.ToString());
item.Tag = entry;
DocList.Items.Add(item);
}
foreach (ColumnHeader column in DocList.Columns)
{
column.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
}
}Variabel imageKey memilih gambar mana dalam ImageList terkait yang harus digunakan untuk setiap baris. Properti Tag digunakan di sini untuk menyimpan entri asli, yang dapat berguna untuk melakukan operasi pada dokumen nanti. Terakhir, metode AutoResize digunakan untuk memformat lebar kolom secara otomatis di ListView.
Membuka Dokumen di Browser
Karena dokumen ini disimpan di Google Dokumen, sebaiknya izinkan pengguna melihat dokumen di browser mereka. Ada fungsi bawaan untuk melakukannya di Windows:
using System.Diagnostics;
private void OpenSelectedDocument()
{
if (DocList.SelectedItems.Count > 0)
{
DocumentEntry entry = (DocumentEntry) DocList.SelectedItems[0].Tag;
Process.Start(entry.AlternateUri.ToString());
}
}
Di sini, kita mengambil kembali entri asli dari properti Tag, lalu menggunakan AlternateUri dokumen yang dipilih untuk memanggil Process.Start. Sisanya ditangani oleh keajaiban .NET Framework.
Menambahkan Menu Konteks Shell
Cara paling sederhana untuk menambahkan item ke menu konteks shell adalah dengan mengubah registri. Yang perlu kita lakukan adalah membuat entri di HKEY_CLASSES_ROOT yang mengarah ke aplikasi kita. Perhatikan bahwa tindakan ini akan membuka instance baru aplikasi kita saat pengguna mengklik item menu, yang akan kita bahas di bagian berikutnya.
using Microsoft.Win32;
public void Register()
{
RegistryKey key = Registry.ClassesRoot.OpenSubKey("*\\shell\\"+KEY_NAME+"\\command");
if (key == null)
{
key = Registry.ClassesRoot.CreateSubKey("*\\shell\\" + KEY_NAME + "\\command");
}
key.SetValue("", Application.ExecutablePath + " \"%1\"");
}Kode ini membuat kunci registry tempat aplikasi yang sedang berjalan berada. Notasi "%1" digunakan untuk menunjukkan bahwa file yang dipilih di shell harus diteruskan di dalam parameter ini. KEY_NAME adalah konstanta string yang ditentukan yang menentukan teks entri di menu konteks.
public void UnRegister()
{
RegistryKey key = Registry.ClassesRoot.OpenSubKey("*\\shell\\"+KEY_NAME);
if (key != null)
{
Registry.ClassesRoot.DeleteSubKeyTree("*\\shell\\"+KEY_NAME);
}
}Metode ini hanya menghapus kunci kustom yang kita tambahkan, jika ada.
Mencegah Beberapa Instance
Karena aplikasi kita berada di area notifikasi sistem, kita tidak ingin beberapa instance program berjalan sekaligus. Kita dapat menggunakan Mutex untuk memastikan hanya satu instance yang tetap berjalan.
using System.Threading;
bool firstInstance;
Mutex mutex = new Mutex(true, "Local\\DocListUploader", out firstInstance);
if (!firstInstance)
{
return;
}Kode di atas dapat ditempatkan dalam metode Main aplikasi kita untuk keluar lebih awal jika program kita sudah berjalan. Karena Mutex berada dalam namespace "Lokal", sesi yang berbeda di komputer dapat menjalankan aplikasi kita secara terpisah. Namun, beberapa tindakan pencegahan tambahan harus dilakukan karena kita memodifikasi registri global.
Komunikasi Antarproses (IPC)
Saat pengguna mengklik item menu konteks shell untuk file yang kita tambahkan sebelumnya, instance baru aplikasi kita diluncurkan dan diberi jalur lengkap ke lokasi file di disk. Informasi ini sekarang harus dikirimkan ke instance aplikasi yang sudah berjalan. Hal ini dapat dilakukan menggunakan mekanisme IPC .NET Framework yang diperkenalkan di versi 2.0.
using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Ipc;
Pesan yang kita teruskan berbentuk objek kustom. Di sini saya telah membuat objek yang berisi referensi kembali ke HiddenForm yang berisi logika aplikasi ini. Karena objek ini akan dihosting di instance asli, objek ini memberikan cara bagi instance berikutnya untuk berkomunikasi dengan formulir utama instance asli.
class RemoteMessage : MarshalByRefObject
{
private HiddenForm mainForm;
public RemoteMessage(HiddenForm mainForm)
{
this.mainForm = mainForm;
}
public void SendMessage(string file)
{
mainForm.HandleUpload(file);
}
}
Saat instance pertama aplikasi diinisialisasi, kode berikut memungkinkannya memproses instance berikutnya:
public void ListenForSuccessor()
{
IpcServerChannel serverChannel = new IpcServerChannel("DocListUploader");
ChannelServices.RegisterChannel(serverChannel, false);
RemoteMessage remoteMessage = new RemoteMessage(this);
RemotingServices.Marshal(remoteMessage,"FirstInstance");
}Perhatikan di atas bahwa kode tersebut mendaftarkan channel IPC bernama, dan memberikan salinan objek RemoteMessage yang kita tentukan, dengan menginisialisasinya menggunakan referensi ke dirinya sendiri.
Untuk instance program berikutnya, string yang diberikan ke Main melalui parameter args harus diteruskan ke instance asli. Kode berikut dapat dipanggil untuk terhubung ke channel IPC yang mendengarkan dan mengambil objek RemoteMessage dari instance asli. Kemudian, metode SendMessage digunakan untuk meneruskan nama file ke instance asli.
public static void NotifyPredecessor(string file)
{
IpcClientChannel clientChannel = new IpcClientChannel();
ChannelServices.RegisterChannel(clientChannel, false);
RemoteMessage message = (RemoteMessage) Activator.GetObject(typeof(RemoteMessage),
"ipc://DocListUploader/FirstInstance");
if (!message.Equals(null))
{
message.SendMessage(file);
}
}Sistem pesan jarak jauh sangat canggih karena melalui sistem ini kita dapat membuat objek yang termasuk dalam satu instance program kita terlihat melalui saluran IPC lokal ke instance lain.
Kesimpulan
Artikel ini menjelaskan secara umum beberapa metode dan trik yang digunakan dalam contoh DocList Uploader untuk menyediakan utilitas migrasi yang mudah digunakan untuk Google Dokumen. Masih banyak fungsi yang dapat ditambahkan di aplikasi Anda sendiri, dan Anda bebas memperluas contoh agar sesuai dengan tujuan Anda sendiri.
Berikut beberapa referensi berguna bagi developer yang tertarik untuk menggunakan Documents List Data API, serta mereka yang ingin menggunakan .NET dengan Google Data API lainnya: