LAMPIRAN
KUISIONER 1.
2.
Nb.: Jika memilih “Tidak”, lanjutkan ke pertanyaan no. 7. 3.
Nb.: Jika memilih “Tidak”, lanjutkan ke pertanyaan no. 5. 4.
5.
Nb.: Jika memilih “Tidak”, lanjutkan ke pertanyaan no. 7. 6.
L1
L2
7.
8.
9.
Kuisioner dapat dilihat pada: https://docs.google.com/spreadsheet/viewform?formkey=dGpLNGwxYW9CeFQwQ2R XZFZ6eXlkckE6MQ.
L3
HASIL WAWANCARA 1.
Wawancara 1 Nama:
Mayasanti, S. Kom.
Pekerjaan:
Konsultan Pajak
Tanggal Wawancara:
11 Januari 2013
Waktu:
05:00 PM • Bagaimana
Pertanyaan
menurut
Anda
tentang
aplikasi
SeeYou ? • Menurut Anda, apakah kelebihan dan kekurangan yang terdapat pada aplikasi ini? • Ada fitur baru yang namanya self-destroyed message, kirim pesan rahasia jadi aman. • Kelebihannya di self destroyed message, karena saya konsultan pajak, sering banyak pesan sensitif jadi kalau pakai fitur self destroyed message berasa aman. Kelemahannya kurang lengkap fitur untuk chatting-nya. Tabel L.1 Tabel Wawancara 1
2. Wawancara 2 Nama:
Juryan Tumewu, S.Kom, MM.
Pekerjaan:
System Analyst
Tanggal Wawancara:
12 Januari 2013
Waktu:
03:30 PM
Pertanyaan
• Bagaimana
menurut
Anda
tentang
aplikasi
SeeYou ? • Menurut Anda, apakah kelebihan dan kekurangan yang terdapat pada aplikasi ini? • Aplikasi ini memiliki fungsi yang baik dan mudah untuk digunakan. Tampilannya menarik dan menyerupai tampilan instant messaging lainnya.
L4
Informasi lokasi adalah salah satu fitur yang unik karena bisa lebih mengetahui keberadaan teman sehingga bisa mengajak teman untuk bertemu atau makan bersama jika berlokasi berdekatan. • Berikut ini kelebihan dan kekurangan aplikasi “SeeYou”. Kelebihan: - Informasi lokasi yang diberikan jelas. - Pengiriman dan penerimaan pesan cepat. - Fitur search sangat menarik. - Ada profile pengguna. Kelemahan: - Fitur tidak selengkap instant messaging yang sudah ada. - Tidak ada pengaturan yang lebih rinci. Tabel L.2 Tabel Wawancara 2
3. Wawancara 3 Nama:
Junita
Pekerjaan:
Mahasiswi
Tanggal Wawancara:
12 Januari 2013
Waktu:
04:00 PM
Pertanyaan
• Bagaimana menurut Anda tentang aplikasi SeeYou? • Menurut Anda, apakah kelebihan dan kekurangan yang terdapat pada aplikasi ini?
• Bagus, warnanya cerah, ada fitur informasi lokasinya, bisa stalker teman. • Berikut ini kelebihan dan kekurangan aplikasi SeeYou. Kelebihan: - Tampilannya menarik. - Bisa lihat lokasi teman. Kelemahan: - Tidak ada, bagus-bagus saja. Tabel L.3 Tabel Wawancara 3
L5
4. Wawancara 4 Nama:
Angeline
Pekerjaan:
Sales Asuransi
Tanggal Wawancara:
13 Januari 2013
Waktu:
10:00 AM • Bagaimana menurut Anda tentang aplikasi SeeYou?
Pertanyaan
• Menurut Anda, apakah kelebihan dan kekurangan yang terdapat pada aplikasi ini? • Sangat mendukung pekerjaan saya, karena saya sebagai sales asuransi harus mempunyai target yang tepat untuk menawarkan produk saya. • Berikut ini kelebihan dan kekurangan aplikasi SeeYou. Kelebihan: - Bisa mencari orang sesuai kriteria yang saya inginkan. Kelemahan: - Kriterianya kurang banyak. Tabel L.4 Tabel Wawancara 4
5. Wawancara 5 Nama:
Jonathan Samuel
Pekerjaan:
Asisstant Lab Software
Tanggal Wawancara:
13 Januari 2013
Waktu:
11:00 AM
Pertanyaan
• Bagaimana menurut Anda tentang aplikasi SeeYou? • Menurut Anda, apakah kelebihan dan kekurangan yang terdapat pada aplikasi ini?
• Tampilan simple, tapi bagus dan tidak membingungkan. Fitur informasi lokasi teman menarik, bisa mengetahui posisi teman. • Berikut ini kelebihan dan kekurangan aplikasi SeeYou. Kelebihan: - Ada informasi lokasi teman.
L6
- Bisa mengajak teman bertemu jika sedang berdekatan lokasinya. - Bisa menambah teman dengan fitur search. Kelemahan: - Fitur untuk chat kurang menarik. - Tidak bisa kirim foto. Tabel L.5 Tabel Wawancara 5
6. Wawancara 6 Nama :
Eka Prasetya, S.Kom
Pekerjaan :
Project Manager
Tanggal Wawancara :
13 Januari 2013
Waktu :
11:20 AM • Bagaimana menurut Anda tentang aplikasi SeeYou?
Pertanyaan
• Menurut Anda, apakah kelebihan dan kekurangan yang terdapat pada aplikasi ini? • Inovasi baru di instant messenger. • Berikut ini kelebihan dan kekurangan aplikasi SeeYou. Kelebihan: - Fitur self-destroyed message bisa digunakan untuk mengirim password admin ke client. - Fitur search bisa digunakan untuk mencari koneksi bisnis. Kelemahan: - Fitur chat tidak lengkap. - Kriteria search kurang menarik. Tabel L.6 Tabel Wawancara 6
7. Wawancara 7 Nama :
Stefanus Hendriansjah
Pekerjaan :
Restaurant Owner
Tanggal Wawancara :
13 Januari 2013
L7
Waktu :
11:50 AM • Bagaimana menurut Anda tentang aplikasi SeeYou?
Pertanyaan
• Menurut Anda, apakah kelebihan dan kekurangan yang terdapat pada aplikasi ini? • Aplikasi baru yang menarik untuk dicoba. Ada banyak fitur yang belum tersedia di aplikasi sejenisnya. • Berikut ini kelebihan dan kekurangan aplikasi SeeYou. Kelebihan: - Informasi lokasi yang detail mendapatkan lokasi sampai informasi jalan teman. - Ada fitur search yang bisa digunakan untuk memberikan promosi dan diskon restoran. Kelemahan: - Fitur chat tidak lengkap. - Tidak bisa mengirim gambar kepada teman atau orang lain. Tabel L.7 Tabel Wawancara 7
8. Wawancara 8 Nama :
Wira Adiputra
Pekerjaan :
Mahasiswa
Tanggal Wawancara :
13 januari 2013
Waktu :
02:30 PM
Pertanyaan
• Bagaimana menurut Anda tentang aplikasi SeeYou? • Menurut Anda, apakah kelebihan dan kekurangan yang terdapat pada aplikasi ini?
• Cukup bagus, desain menyerupai instant messaging pada umumnya. • Berikut ini kelebihan dan kekurangan aplikasi SeeYou. Kelebihan: - Ada fitur search yang bisa digunakan untuk menambah teman perempuan. Kelemahan:
L8
- Informasi profil untuk filter kurang banyak. Tabel L.8 Tabel Wawancara 8
9. Wawancara 9 Nama :
Rian, S.Kom
Pekerjaan :
Senior Programmer
Tanggal Wawancara :
13 Januari 2013
Waktu :
03:40 PM • Bagaimana menurut Anda tentang aplikasi SeeYou?
Pertanyaan
• Menurut Anda, apakah kelebihan dan kekurangan yang terdapat pada aplikasi ini? • Tampilan tidak menarik, tapi ada fitur bagus yang bisa digunakan. • Berikut ini kelebihan dan kekurangan aplikasi SeeYou. Kelebihan: - Bisa digunakan sebagai social messenger di mana bisa mencari dan menambah teman baru. Kelemahan: - Profil tidak terintegrasi dengan Facebook. Tabel L.9 Tabel Wawancara 9
10. Wawancara 10 Nama :
Dewi Sartika
Pekerjaan :
Staff Administrasi
Tanggal Wawancara :
13 Januari 2013
Waktu :
05:00 PM
Pertanyaan
• Bagaimana
menurut
Anda
tentang
aplikasi
“SeeYou”? • Menurut Anda, apakah kelebihan dan kekurangan yang terdapat pada aplikasi ini? • Banyak fitur baru, tapi fitur untuk chatting tidak sebanyak yang ada.
L9 • Berikut ini kelebihan dan kekurangan aplikasi SeeYou. Kelebihan: - Bisa lihat lokasi teman. - Bisa kenalan banyak orang-orang di sekitar. Kelemahan: - Hanya bisa dipakai di Android saja. - Fitur chat kurang banyak. Tabel L.10 Tabel Wawancara 10
L10
KODE SUMBER (SEBAGIAN) AndroidManifest.xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.benjole.seeyouram" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="10" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<service android:name=".service.LocationService" />
L11 android:name=".app.receiver.ApplicationUpdatedBroadcastReceiver">
Activity.java package com.benjole.seeyouram.activity; import import import import import import import import import import import import import import
java.util.ArrayList; java.util.List; android.content.Context; android.content.pm.ActivityInfo; android.os.Bundle; android.view.LayoutInflater; android.view.View; android.view.Window; android.widget.Button; android.widget.LinearLayout; android.widget.TextView; com.benjole.seeyouram.R; com.benjole.seeyouram.app.SeeYouApplication; com.benjole.seeyouram.view.GlobalWindowButtonManager;
/** * Custom Activity, featuring:
* - Custom window title * - Custom window button */ public class Activity extends android.app.Activity
L12 { private TextView mTitle = null; @Override protected void onCreate(Bundle savedInstanceState) { onCreate(savedInstanceState, false, true); } protected void onCreate(Bundle savedInstanceState, boolean allowScreenRotation) { onCreate(savedInstanceState, allowScreenRotation, true); } protected void onCreate(Bundle savedInstanceState, boolean allowScreenRotation, boolean showTitle) { super.onCreate(savedInstanceState); // Set uncaught exception handler. Thread.setDefaultUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread thread, Throwable ex) { Thread.getDefaultUncaughtExceptionHandler() .uncaughtException(thread, ex); } }); // Store current activity for global use. SeeYouApplication.setCurrentActivity(this); if (!allowScreenRotation) setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); if (showTitle) { if (getParent() == null) { requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); setContentView(R.layout.hello_world); getWindow().setFeatureInt( Window.FEATURE_CUSTOM_TITLE, R.layout.window_title); mTitle = (TextView)findViewById(R.id.title); } else { mTitle = (TextView) getParent() .findViewById(R.id.title); }
L13
if (mWindowButtonContainer == null) { if (getParent() == null) mWindowButtonContainer = (LinearLayout) getWindow().findViewById( R.id.customWindow_ButtonContainer); else mWindowButtonContainer = (LinearLayout) getParent().getWindow().findViewById( R.id.customWindow_ButtonContainer); } } } @Override protected void onResume() { super.onResume(); // Store current activity for global use. SeeYouApplication.setCurrentActivity(this); } @Override public void setTitle(CharSequence title) { if (mTitle != null) mTitle.setText(title); } @Override public void setTitleColor(int textColor) { if (mTitle != null) mTitle.setTextColor(textColor); } private LayoutInflater mInflater = null; private LinearLayout mWindowButtonContainer = null; private List<String> mLocalWindowButtonTags = new ArrayList<String>(); public LayoutInflater getLayoutInflater() { if (mInflater == null) mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); return mInflater; } public LinearLayout getWindowButtonContainer() { return mWindowButtonContainer; } public Button addWindowButton(int imageResId, View.OnClickListener clickListener, boolean localOnly) {
L14 return addWindowButton("", imageResId, clickListener, localOnly); } public Button addWindowButton(String text, View.OnClickListener clickListener, boolean localOnly) { return addWindowButton("", text, clickListener, localOnly); } public Button addWindowButton(String tag, int imageResId, View.OnClickListener clickListener, boolean localOnly) { if (mInflater == null) mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); final Button button = (Button) mInflater.inflate(R.layout.window_button, null); button.setTag(tag); button.setBackgroundResource(imageResId); button.setLayoutParams( SeeYouApplication.getWindowButtonLayoutParams()); boolean hasClickListener = (clickListener != null); if (hasClickListener) button.setOnClickListener(clickListener); button.setClickable(hasClickListener); button.setFocusable(hasClickListener); if (localOnly) { mWindowButtonContainer.addView(button, GlobalWindowButtonManager.getInstance() .getWindowButtonCount()); mLocalWindowButtonTags.add(tag); } else mWindowButtonContainer.addView(button, 0); return button; } public Button addWindowButton(String tag, String text, View.OnClickListener clickListener, boolean localOnly) { if (mInflater == null) mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); final Button button = (Button) mInflater.inflate(R.layout.window_button, null); button.setTag(tag); button.setText(text); button.setOnClickListener(clickListener); boolean hasClickListener = (clickListener != null); if (hasClickListener) button.setOnClickListener(clickListener); button.setClickable(hasClickListener);
L15 button.setFocusable(hasClickListener); if (localOnly) { mWindowButtonContainer.addView(button, GlobalWindowButtonManager.getInstance() .getWindowButtonCount()); mLocalWindowButtonTags.add(tag); } else mWindowButtonContainer.addView(button, 0); return button; } public void addWindowButton(final Button button) { mWindowButtonContainer.addView(button, 0); } public Button updateWindowButton(String tag, View.OnClickListener clickListener) { final Button button = findButtonByTag(tag); if (button != null) button.setOnClickListener(clickListener); return button; } public Button updateWindowButton(String tag, int imageResId, View.OnClickListener clickListener) { final Button button = findButtonByTag(tag); if (button != null) { button.setBackgroundResource(imageResId); button.setOnClickListener(clickListener); } return button; } public Button updateWindowButton(String tag, String text, View.OnClickListener clickListener) { final Button button = findButtonByTag(tag); if (button != null) { button.setText(text); button.setOnClickListener(clickListener); } return button; } public void removeLocalWindowButtons() { for (String tag : mLocalWindowButtonTags)
L16 removeWindowButton(tag); } public void removeWindowButton(Button button) { mWindowButtonContainer.removeView(button); } public void removeWindowButton(String tag) { final Button button = findButtonByTag(tag); if (button != null) mWindowButtonContainer.removeView(button); } private Button findButtonByTag(String tag) { View view = mWindowButtonContainer.findViewWithTag(tag); if (view != null) return (Button)view; return null; } }
ChattingActivity.java package com.benjole.seeyouram.activity; import import import import import import import import import import import import import import import import import import import import import import import import import import import
java.util.ArrayList; java.util.LinkedHashMap; java.util.Map; java.util.Map.Entry; android.app.AlertDialog; android.content.Context; android.content.DialogInterface; android.graphics.Color; android.os.Bundle; android.text.Spannable; android.text.SpannableStringBuilder; android.text.style.ImageSpan; android.view.ContextMenu; android.view.ContextMenu.ContextMenuInfo; android.view.Gravity; android.view.LayoutInflater; android.view.Menu; android.view.MenuItem; android.view.View; android.view.ViewGroup; android.view.WindowManager; android.widget.AdapterView; android.widget.AdapterView.AdapterContextMenuInfo; android.widget.AdapterView.OnItemClickListener; android.widget.ArrayAdapter; android.widget.Button; android.widget.CheckBox;
L17
import import import import import import import import import import import import import import import import import import import import import import
android.widget.CompoundButton; android.widget.EditText; android.widget.GridView; android.widget.LinearLayout; android.widget.LinearLayout.LayoutParams; android.widget.ListView; android.widget.PopupWindow; android.widget.Spinner; com.benjole.seeyouram.R; com.benjole.seeyouram.app.SeeYouApplication; com.benjole.seeyouram.app.config.MessageConfig; com.benjole.seeyouram.app.persistence.ChatHistoryPersistence; com.benjole.seeyouram.app.persistence.ChatPersistence; com.benjole.seeyouram.app.persistence.SessionPersistence; com.benjole.seeyouram.model.ChatHistoryItemData; com.benjole.seeyouram.model.UserData; com.benjole.seeyouram.utils.ConnectionUtils; com.benjole.seeyouram.utils.UiUtils; com.benjole.seeyouram.view.GlobalWindowButtonManager; com.benjole.seeyouram.widget.adapter.ChatItemAdapter; com.benjole.seeyouram.widget.adapter.EmoticonAdapter; com.benjole.seeyouram.xmpp.XMPPClient;
/** * Show user's list of chats with selected user. */ public class ChattingActivity extends Activity { private static final String WINDOW_TITLE = "Chat"; private static final int MENU_OPTION_CLEAR = 1; private static final int MENU_OPTION_REFRESH = 2; public static final String KEY_WITH_ID = SeeYouApplication.PACKAGE_NAME + ".WithID"; public static final String KEY_WITH_NAME = SeeYouApplication.PACKAGE_NAME + ".WithName"; private final String mUserID = SessionPersistence.getInstance().getUserID(); private private private private
String mWithUserID, mWithUserName; ChatPersistence mChatPersistence; int mSelfDestroyTime; boolean mIsNewCreate = false;
public boolean isChattingWith(String userID) { return mWithUserID.equals(userID); } private LinearLayout mLayout; private ListView mListView; private EditText mTextMessage;
L18 private Button private PopupWindow private GridView
mWindowButtonSD = null; mEmoticonWindow = null; mEmoticonGridView;
private Map<String, Integer> mEmoticonMapping = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mIsNewCreate = true; findFriendUserIDandName(); initViews(); mSelfDestroyTime = 0; // Add window button for self-destroy setting. mWindowButtonSD = addWindowButton("sdSetting", R.drawable.sd_off, new View.OnClickListener() { public void onClick(View v) { if (mSelfDestroyTime > 0) setSelfDestroyed(0); else SelfDestroySettingWindow .getInstance(ChattingActivity.this) .show(); } }, true); GlobalWindowButtonManager.getInstance() .showAllWindowButtons(this); loadChatItemList(); } @Override protected void onResume() { super.onResume(); setTitle(WINDOW_TITLE + " (" + mWithUserName + ")"); if (!mIsNewCreate) { if (mWithUserID == null || mWithUserID == "" || mChatPersistence == null) { findFriendUserIDandName(); loadChatItemList(); } } } @Override
L19 protected void onPause() { super.onPause(); mIsNewCreate = false; } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0, MENU_OPTION_CLEAR, 0, "Clear All"); menu.add(0, MENU_OPTION_REFRESH, 0, "Refresh"); return true; } @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { if (item.getItemId() == MENU_OPTION_CLEAR) { clearChatItemList(); } else if (item.getItemId() == MENU_OPTION_REFRESH) { loadChatItemList(); } return super.onMenuItemSelected(featureId, item); } @Override public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, view, menuInfo); menu.add(0, ContextMenuItem.REMOVE_ITEM, 4, "Remove Item"); } @Override public boolean onContextItemSelected(MenuItem item) { final int position = ((AdapterContextMenuInfo)item.getMenuInfo()).position; switch(item.getItemId()) { case ContextMenuItem.REMOVE_ITEM: // Remove selected chat item. ChatPersistence.getInstance(mWithUserID) .removeChatItem(position); ((ChatItemAdapter)mListView.getAdapter()) .notifyDataSetChanged(); break; } return super.onContextItemSelected(item);
L20 } private void findFriendUserIDandName() { mWithUserID = getIntent().getStringExtra(KEY_WITH_ID); mWithUserName = getIntent().getStringExtra(KEY_WITH_NAME); if (mWithUserName == null || mWithUserName.isEmpty()) { UserData user = SessionPersistence.getInstance() .getFriend(mWithUserID); if (user != null) mWithUserName = user.getFullName(); } if (mWithUserName == null || mWithUserName.isEmpty()) { ChatHistoryItemData c = ChatHistoryPersistence .getInstance().getChatHistoryItem(mWithUserID); if (c != null) mWithUserName = c.getWithUserName(); } if (mWithUserName == null || mWithUserName.isEmpty()) mWithUserName = mWithUserID; mChatPersistence = ChatPersistence.getInstance(mWithUserID); } private void initViews() { setContentView(R.layout.chatting); mLayout = (LinearLayout) findViewById(R.id.layout_root); mListView = (ListView) findViewById(android.R.id.list); mTextMessage = (EditText) findViewById(R.id.txt_message); registerForContextMenu(mListView); findViewById(R.id.layout_root).requestFocus(); // Check network connection status. if (!ConnectionUtils.isNetworkAvailable() || !XMPPClient.getInstance().getConnection().isAuthenticated()) { UiUtils.showToast("Not connected to chat service," + "please check your connection settings and relogin"); mTextMessage.setText(MessageConfig.NOT_CONNECTED); mTextMessage.setEnabled(false); findViewById(R.id.btn_submit).setEnabled(false); findViewById(R.id.btn_emoticon).setEnabled(false); } // Initialize emoticon window. initEmoticonWindow(); setEventHandlers(); } private void initEmoticonWindow() { mEmoticonMapping = new LinkedHashMap<String, Integer>(17);
L21 mEmoticonMapping.put("O:-)", Integer.valueOf(R.drawable.emo_im_angel)); mEmoticonMapping.put("B-)", Integer.valueOf(R.drawable.emo_im_cool)); mEmoticonMapping.put(":'(", Integer.valueOf(R.drawable.emo_im_crying)); mEmoticonMapping.put(":\">", Integer.valueOf(R.drawable.emo_im_embarrassed)); mEmoticonMapping.put("=D~", Integer.valueOf(R.drawable.emo_im_foot_in_mouth)); mEmoticonMapping.put(":-)", Integer.valueOf(R.drawable.emo_im_happy)); mEmoticonMapping.put(":-*", Integer.valueOf(R.drawable.emo_im_kissing)); mEmoticonMapping.put(":-D", Integer.valueOf( R.drawable.emo_im_laughing)); mEmoticonMapping.put(":-X", Integer.valueOf(R.drawable.emo_im_lips_are_sealed)); mEmoticonMapping.put("$-|", Integer.valueOf(R.drawable.emo_im_money_mouth)); mEmoticonMapping.put(":-(", Integer.valueOf(R.drawable.emo_im_sad)); mEmoticonMapping.put(":-O", Integer.valueOf(R.drawable.emo_im_surprised)); mEmoticonMapping.put(":-P", Integer.valueOf(R.drawable.emo_im_tongue_sticking_out)); mEmoticonMapping.put(":-\\", Integer.valueOf(R.drawable.emo_im_undecided)); mEmoticonMapping.put(";-)", Integer.valueOf(R.drawable.emo_im_winking)); mEmoticonMapping.put(":-|", Integer.valueOf(R.drawable.emo_im_wtf)); mEmoticonMapping.put(":-@", Integer.valueOf(R.drawable.emo_im_yelling)); LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); mEmoticonGridView = (GridView) inflater.inflate(R.layout.emoticons, (ViewGroup) findViewById(R.id.grid_view)); mEmoticonGridView.setAdapter(new EmoticonAdapter(this, mEmoticonMapping)); int width = UiUtils.convertDIPtoPixel(5 * 48 + 5 * 8 + 4); int height = UiUtils.convertDIPtoPixel(4 * 48 + 4 * 8 + 4); mEmoticonWindow = new PopupWindow(mEmoticonGridView, width, height, true); mEmoticonWindow.setFocusable(true); mEmoticonWindow.setOutsideTouchable(true); mEmoticonWindow.setBackgroundDrawable( getResources().getDrawable(R.drawable.transparent)); } private void setEventHandlers()
L22 { // Set click listener for send button. findViewById(R.id.btn_submit).setOnClickListener( new View.OnClickListener() { public void onClick(View v) { sendChat(); } }); // Set click listener for emoticon button. final int OFFSET_X = UiUtils.convertDIPtoPixel(8); final int OFFSET_Y = UiUtils.convertDIPtoPixel(60); findViewById(R.id.btn_emoticon).setOnClickListener( new View.OnClickListener() { public void onClick(View v) { mEmoticonWindow.showAtLocation(mLayout, Gravity.LEFT | Gravity.BOTTOM, OFFSET_X, OFFSET_Y); } }); // Set item click listener for emoticon grid view. mEmoticonGridView.setOnItemClickListener( new OnItemClickListener() { public void onItemClick(AdapterView> adapterView, View view, int position, long id) { String tag = view.getTag().toString(); String curText = mTextMessage.getText().toString(); int curSelection = mTextMessage .getSelectionStart(); String text = ""; if (curSelection == curText.length()) text = curText + tag; else text = curText.substring(0, curSelection) + tag + curText.substring(curSelection); Spannable parsed = parseEmoticon(text); mTextMessage.setText(parsed); mTextMessage.setSelection( curSelection + tag.length()); mTextMessage.requestFocus(); mEmoticonWindow.dismiss(); getWindow().setSoftInputMode( WindowManager.LayoutParams .SOFT_INPUT_STATE_ALWAYS_VISIBLE); } }); }
L23
private Spannable parseEmoticon(String text) { SpannableStringBuilder builder = new SpannableStringBuilder(text); for (int index = 0; index < builder.length(); index++) { for (Entry<String, Integer> entry : mEmoticonMapping.entrySet()) { int length = entry.getKey().length(); if (index + length > builder.length()) continue; String k = builder.subSequence(index, index + length).toString(); if (k.equals(entry.getKey())) { int imgResId = entry.getValue().intValue(); ImageSpan imgSpan = new ImageSpan(ChattingActivity.this, imgResId); builder.setSpan(imgSpan, index, index + length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); index += length - 1; break; } } } return builder; } private void sendChat() { final String msg = mTextMessage.getText().toString(); if (!msg.equals("")) { mTextMessage.setText(""); new Thread(new Runnable() { public void run() { try { final boolean isSelfDestroy = mSelfDestroyTime > 0; final long time = SeeYouApplication .getServerTimeMillis(); if (isSelfDestroy) { mChatPersistence.addChatItem( mUserID, mWithUserID, true, msg,
L24 time, 0, mSelfDestroyTime); XMPPClient.getInstance() .sendMessage(mWithUserID, msg, mSelfDestroyTime); } else { mChatPersistence.addChatItem( mUserID, mWithUserID, true, msg, time, 0); XMPPClient.getInstance() .sendMessage(mWithUserID, msg); } // Add to chat history. ChatHistoryPersistence.getInstance() .addChatHistoryItem(mWithUserID, mWithUserName, msg, time, isSelfDestroy); runOnUiThread(new Runnable() { public void run() { loadChatItemList(); } }); } catch (Exception e) { UiUtils.showToast( ChattingActivity.this, "Error: " + e.getMessage() == null ? e.toString() : e.getMessage()); } } }).start(); } mTextMessage.requestFocus(); } public void loadChatItemList() { final ChatItemAdapter adapter = new ChatItemAdapter(this, mWithUserID, mEmoticonMapping); mListView.setAdapter(adapter); if (adapter.getCount() > 0) mListView.setSelection(adapter.getCount() - 1); } public void updateChatItemList() {
L25 final ChatItemAdapter adapter = (ChatItemAdapter) mListView.getAdapter(); adapter.notifyDataSetChanged(); } private void clearChatItemList() { if (mListView.getAdapter().getCount() > 0) { new AlertDialog.Builder(ChattingActivity.this) .setMessage("Are you sure?") .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { ChatPersistence.getInstance(mWithUserID) .erase(); UiUtils.showToast( "The chat item list has been clear"); mChatPersistence = ChatPersistence .getInstance(mWithUserID); loadChatItemList(); } }) .setNegativeButton("Cancel", null) .show(); } else UiUtils.showToast("The chat item list is empty"); } private void setSelfDestroyed(final int sdTime) { mSelfDestroyTime = sdTime; mWindowButtonSD.setBackgroundResource( sdTime == 0 ? R.drawable.sd_off : R.drawable.sd_on); if (sdTime > 0) { UiUtils.showToast("SD after " + sdTime + (sdTime == 1 ? " minute" : " minutes")); } else UiUtils.showToast("SD message is turned off"); } private static class ContextMenuItem { private static final int REMOVE_ITEM = 4; } private static class SelfDestroySettingWindow { private static final int PADDING = UiUtils.convertDIPtoPixel(8);
L26 private static SelfDestroySettingWindow mWindow = null; private static ChattingActivity mActivity; public static SelfDestroySettingWindow getInstance( ChattingActivity activity) { mActivity = activity; if (mWindow == null) mWindow = new SelfDestroySettingWindow(activity); return mWindow; } private int[] mArrSDLength; private ArrayList<String> mListOptions; private int mLastSelectedIndex = 0; public SelfDestroySettingWindow(final ChattingActivity activity) { mArrSDLength = activity.getResources() .getIntArray(R.array.arr_self_destroy_length); mListOptions = new ArrayList<String>(mArrSDLength.length); mListOptions.add( Integer.toString(mArrSDLength[0]) + " minute"); for (int i = 1; i < mArrSDLength.length; i++) mListOptions.add(Integer.toString(mArrSDLength[i]) + " minutes"); } public void show() { LayoutParams layoutParams = new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); // Create CheckBox to turn self-destroyed message on/off. final CheckBox chkSD = new CheckBox(mActivity); chkSD.setChecked(mActivity.mSelfDestroyTime > 0); chkSD.setText(" Self-destroy after:"); chkSD.setTextColor(Color.WHITE); chkSD.setLayoutParams(layoutParams); // Create adapter for Spinner. ArrayAdapter<String> adapter = new ArrayAdapter<String>(mActivity, android.R.layout.simple_spinner_item, mListOptions); adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item); // Create Spinner to set the lifetime of the message // before it self-destroyed (in minutes). final Spinner spinMinutes = new Spinner(mActivity); spinMinutes.setAdapter(adapter); spinMinutes.setLayoutParams(layoutParams);
L27 spinMinutes.setEnabled(chkSD.isChecked()); spinMinutes.setSelection(mLastSelectedIndex); // Add event listener to chkSD. chkSD.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() { public void onCheckedChanged( CompoundButton buttonView, boolean isChecked) { spinMinutes.setEnabled(isChecked); } }); // Create main layout for the dialog and // add created EditText to it. LinearLayout layout = getVerticalLayout(mActivity); layout.addView(chkSD); layout.addView(spinMinutes); // Create the dialog. new AlertDialog.Builder(mActivity) .setTitle("Self-Destroyed Setting") .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick( DialogInterface dialog, int which) { mLastSelectedIndex = spinMinutes .getSelectedItemPosition(); int time = 0; if (chkSD.isChecked()) { time = mArrSDLength[mLastSelectedIndex]; mActivity.setSelfDestroyed(time); } } }) .setNegativeButton("Cancel", null) .setView(layout) .show(); } private LinearLayout getVerticalLayout(Context context) { LinearLayout layout = new LinearLayout(context); layout.setOrientation(LinearLayout.VERTICAL); layout.setLayoutParams(new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); layout.setPadding(PADDING, PADDING, PADDING, PADDING);
L28 layout.setGravity(Gravity.CENTER); return layout; } } }
UnreadChatPersistence.java package com.benjole.seeyouram.app.persistence; import import import import import import import import import import import import import import
java.io.FileInputStream; java.io.FileOutputStream; java.io.IOException; java.io.ObjectInputStream; java.io.ObjectOutputStream; java.io.Serializable; java.util.Date; java.util.Vector; android.content.Context; com.benjole.seeyouram.app.SeeYouApplication; com.benjole.seeyouram.model.ChatItemData; com.benjole.seeyouram.utils.DateUtils; com.benjole.seeyouram.utils.ExceptionUtils; com.benjole.seeyouram.utils.StringUtils;
/** * Unread chat messages persistence class. */ public class UnreadChatPersistence implements Serializable { // DO NOT touch this property! private static final long serialVersionUID = 9117063163211039207L; private static final String TAG = "UnreadChatPersistence"; private static final String PERSISTENCE_ID = StringUtils.convertToSHA1(UnreadChatPersistence.class.getName()); private static UnreadChatPersistence mPersistence = null; private static String mOwnerUserID = ""; /** * Gets the instance of unread chat persistence. * @param withUserID The user ID which the client is chatting with. * @return Instance of chat persistence. */ public static UnreadChatPersistence getInstance() { final String currentUserID = SessionPersistence.getInstance().getUserID(); if (!currentUserID.equals(mOwnerUserID)) { mOwnerUserID = currentUserID;
L29 mPersistence = null; } if (mPersistence == null) { try { FileInputStream fis = SeeYouApplication .getInstance().getApplicationContext() .openFileInput(PERSISTENCE_ID); ObjectInputStream in = new ObjectInputStream(fis); mPersistence = (UnreadChatPersistence) in.readObject(); in.close(); fis.close(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } if (mPersistence == null) mPersistence = new UnreadChatPersistence(); } return mPersistence; } private Vector<String> mListUnreadChat = null; private int mUnreadChatCount = 0; // Declare private constructor to prevent instance // to be created from this class outside. private UnreadChatPersistence() { mListUnreadChat = new Vector<String>(4); mUnreadChatCount = 0; } public Vector<String> getUnreadChatUsers() { return mListUnreadChat; } public Vector
getUnreadChatItems() { synchronized (mListUnreadChat) { Vector listChat = new Vector(mListUnreadChat.size()); for (String userID : mListUnreadChat) listChat.add( ChatPersistence.getInstance(userID)
L30 .getLastChatItem()); return listChat; } } public int getNumberOfUnreadChat() { return mUnreadChatCount; } public boolean hasUnreadChats() { return mUnreadChatCount > 0; } public boolean hasUnreadChat(final String userID) { return mListUnreadChat.contains(userID); } public void addUnreadChat(String senderUserID) { if (!mListUnreadChat.contains(senderUserID)) { synchronized (mListUnreadChat) { mListUnreadChat.add(senderUserID); mUnreadChatCount++; persist(); } } } public void markAsRead(String userID) { synchronized (mListUnreadChat) { if (mListUnreadChat.remove(userID)) { mUnreadChatCount--; persist(); } } } public void clearAll() { synchronized (mListUnreadChat) { mListUnreadChat.removeAllElements(); mUnreadChatCount = 0; persist(); } }
L31
public void erase() { Context context = SeeYouApplication.getInstance().getApplicationContext(); if (!context.deleteFile(PERSISTENCE_ID)) { try { FileOutputStream fos = context.openFileOutput(PERSISTENCE_ID, 0); ObjectOutputStream out = new ObjectOutputStream(fos); out.writeObject(new UnreadChatPersistence()); out.close(); fos.close(); } catch (IOException e) { ExceptionUtils.logException(e, TAG); } } } public void persist() { mPersistence = this; try { FileOutputStream fos = SeeYouApplication.getInstance() .getApplicationContext() .openFileOutput(PERSISTENCE_ID, 0); ObjectOutputStream out = new ObjectOutputStream(fos); out.writeObject(this); out.close(); fos.close(); } catch (IOException e) { ExceptionUtils.logException(e, TAG); } } }
*.java