Android4.0下的Calendar、events、reminder簡單Demo

上週花了不到一個周研究了一下android中的Calendar這個東西,下面把我的收穫與大家分享一下。

我的研究是從閱讀官方文檔開始的。官方文檔上的開頭部分涉及到了一個ContentProvider和ContentResolver的東西。這個概念在android開發中很重要。

爲了在應用程序之間交換數據,android提供了ContentProvider,ContentProvider是不同應用程序之間進行數據交換的標準API,當一個應用程序需要把自己的數據暴露給其他程序使用時,該應用程序就可以通過提供ContentProvider實現。其他應用程序就可以通過ContentResolver來操作ContentProvider暴露的數據(一般是以數據庫的一個表的形式暴露,因此用ContentResolver操作數據時,也很類似對數據庫的表的操作)。

ContentProvider也是android應用的四大組件之一,與Activity、Service、BroadcastReceiver相似,它們都需要在AndroidManifest.xml中配置。

還有,一般來說,ContentProvider是單例模式的,當多個應用程序通過ContentResolver來操作ContentProvider提供的數據時,ContentResolver調用的數據將會委託給同一個ContentProvider處理。

一旦某個應用程序通過ContentProvider暴露了自己的數據操作接口,那麼不管該應用程序是否啓動,其他應用程序都可以通過該接口來操作該應用程序的內部數據,包括增刪改查。

還有一個很重要的東西叫Uri(不是Url,其實和Url作用很像的)。通俗一點說就是當你用ContentResolver操作數據時,用Uri來指明數據的url。

使用ContentResolver操作數據的步驟其實很簡單:首先調用Activity的getContentResolver( )獲取ContentResolver對象,然後根據需要調用ContentResolver的insert( )、update( )、delete( ) 和query方法操作數據即可。爲了操作數據,我們需要了解ContentProvider的Uri。這也是上述三個概念的簡單聯繫。

扯了這麼多,其實這個Demo中ContentProvider和ContentResolver的概念體現的不是很明顯。因爲我們用的是操作系統給我們的ContentProvider,然後我們自己獲取ContentResolver對象來操作數據,只需要瞭解系統的響應的ContentProvider的Uri即可。

這個Demo實現了爲手機上的某個賬戶添加新的event(併爲新添加的event添加reminder),查詢所有賬戶的所有Calendar,刪除event等(修改event只需要類似地調用ContentResolver的相應的方法即可,本Demo沒有實現),其他還用到了將手機設置成震動,全局定時器、焦點事件以及TimePickerDialog、DatePickerDialog等,下面上圖:

Android4.0第一次使用引導


Android4.0待機

下面是本Demo的效果:


下面是AndroidCalendarProviderTestActivity.java的代碼:

package org.ls;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Events;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class AndroidCalendarProviderTestActivity extends Activity {
	private Button showCalendars;
	private Button addEvents;
	private Button queryEvents;
	private TextView displayEnvents;
	private EditText getEventIdEditText;
	private Button delEvent;

	public static final String[] EVENT_PROJECTION = new String[] {
			Calendars._ID, Calendars.ACCOUNT_NAME,
			Calendars.CALENDAR_DISPLAY_NAME };
	private static final int PROJECTION_ID_INDEX = 0;
	private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
	private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;

	long myEventsId = 0;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		displayEnvents = (TextView) findViewById(R.id.displayevents);
		displayEnvents.setMovementMethod(ScrollingMovementMethod.getInstance());

		showCalendars = (Button) findViewById(R.id.querycalendars);
		showCalendars.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				Cursor cur = null;
				ContentResolver cr = getContentResolver();
				Uri uri = Calendars.CONTENT_URI;
				// String selection = "((" + Calendars.ACCOUNT_NAME +  // 給出查詢條件,查詢特定用戶的日曆
				// " = ?) AND ("+ Calendars.ACCOUNT_TYPE + " = ?))";
				// String[] selectionArgs = new String[]
				// {"[email protected]", "com.google"};
				cur = cr.query(uri, EVENT_PROJECTION, null, null, null); // 查詢條件爲null,查詢所有用戶的所有日曆
				while (cur.moveToNext()) {
					long calID = 0;
					String displayName = null;
					String accountName = null;

					calID = cur.getLong(PROJECTION_ID_INDEX);
					displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
					accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
					
					showMessageDialog("日曆ID:" + calID + "\n" + "日曆顯示名稱:" + "\n"
							+ displayName + "\n" + "日曆擁有者賬戶名稱:" + "\n"
							+ accountName);
				}
			}

		});

		addEvents = (Button) findViewById(R.id.addevents);
		addEvents.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent itent=new Intent();
				itent.setClass(AndroidCalendarProviderTestActivity.this,AddNewEventActivity.class);
				startActivity(itent); // 啓動添加新event的Activity
			}
		});

		queryEvents = (Button) findViewById(R.id.queryevents);
		queryEvents.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				ContentResolver cr = getContentResolver();
				Cursor cur = cr.query(Events.CONTENT_URI, new String[] {
						Events._ID, Events.TITLE, Events.DESCRIPTION,
						Events.DTSTART, Events.DTEND },
				/* Events._ID + "=" + myEventsId */null, null, null); // 註釋中的條件是是查詢特定ID的events
				displayEnvents.setText("");
				while (cur.moveToNext()) {
					Long tempEventsId = cur.getLong(0);
					String tempEventsTitle = cur.getString(1);
					String tempEventsDecription = cur.getString(2);
					String tempEventsStartTime = cur.getString(3);
					String tempEventsEndTime = cur.getString(4);
					displayEnvents.append(tempEventsId + "\n");
					displayEnvents.append(tempEventsTitle + " "
							+ tempEventsDecription + "\n");
					displayEnvents.append(new SimpleDateFormat(
							"yyyy/MM/dd hh:mm").format(new Date(Long
							.parseLong(tempEventsStartTime)))
							+ "至");
					displayEnvents.append(new SimpleDateFormat(
							"yyyy/MM/dd hh:mm").format(new Date(Long
							.parseLong(tempEventsEndTime)))
							+ "\n");
				}
			}
		});

		getEventIdEditText = (EditText) findViewById(R.id.geteventid);
		delEvent = (Button) findViewById(R.id.delevent);
		delEvent.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				Long tempEventId = 0l;
				try {
					tempEventId = Long.parseLong(getEventIdEditText.getText()
							.toString());
				} catch (Exception e) {
					showMessageDialog("請先查詢所有event,然後正確填寫event的id~");
					return;
				}
				// 另一種刪除event方式
				// Uri deleteUri =
				// ContentUris.withAppendedId(Events.CONTENT_URI, tempEventId);
				// int rows = getContentResolver().delete(deleteUri, null,
				// null);
				ContentResolver cr = getContentResolver();
				int rows = cr.delete(Events.CONTENT_URI, Events._ID + "= ?",
						new String[] { tempEventId + "" });

				showMessageDialog("刪除了一個event:" + rows);
				Log.i("delete_event", "Rows deleted: " + rows);
			}
		});

	}

	public void showMessageDialog(String info) { // 彈出消息對話框,消息的內容是info 
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(info);
		builder.setTitle("information");
		builder.setPositiveButton("確定", null);
		AlertDialog alert = builder.create();
		alert.show();
	}
}

下面是AddNewActivity.java的代碼:

package org.ls;

import java.util.Calendar;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.PendingIntent;
import android.app.Service;
import android.app.TimePickerDialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CalendarContract.Events;
import android.provider.CalendarContract.Reminders;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TimePicker;

public class AddNewEventActivity extends Activity implements OnClickListener,
		OnFocusChangeListener {

	public String eventName;
	public String eventDescription;
	public int[] eventBeginDate = new int[3];
	public int[] eventBeginTime = new int[2];
	public int[] eventEndDate = new int[3];
	public int[] eventEndTime = new int[2];
	public int reminderMinutes;

	private EditText eventNameText;
	private EditText eventDescriptionText;
	private EditText eventBeginDateText;
	private EditText eventBeginTimeText;
	private EditText eventEndDateText;
	private EditText eventEndTimeText;
	private EditText reminderminutesText;

	private Button okButton;
	private Button goBackButton;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.add_event);

		okButton = (Button) findViewById(R.id.ok);
		okButton.setOnClickListener(this);
		goBackButton = (Button) findViewById(R.id.goback);
		goBackButton.setOnClickListener(this);

		eventNameText = (EditText)findViewById(R.id.event_name);
		eventDescriptionText = (EditText)findViewById(R.id.event_description);
		
		eventBeginDateText = (EditText) findViewById(R.id.select_begin_date);
		eventBeginDateText.setFocusable(true);
		eventBeginDateText.setOnFocusChangeListener(this);

		eventBeginTimeText = (EditText) findViewById(R.id.select_begin_time);
		eventBeginTimeText.setFocusable(true);
		eventBeginTimeText.setOnFocusChangeListener(this);

		eventEndDateText = (EditText) findViewById(R.id.select_end_date);
		eventEndDateText.setFocusable(true);
		eventEndDateText.setOnFocusChangeListener(this);

		eventEndTimeText = (EditText) findViewById(R.id.select_end_time);
		eventEndTimeText.setFocusable(true);
		eventEndTimeText.setOnFocusChangeListener(this);

		reminderminutesText = (EditText) findViewById(R.id.reminder_minutes);
	}

	@Override
	public void onClick(View v) {
		if (v == okButton) {
			eventName = eventNameText.getText().toString();
			eventDescription = eventDescriptionText.getText().toString();
			reminderMinutes = Integer.parseInt(reminderminutesText.getText()
					.toString());
			// 可在此處添加簡單的判斷用戶輸入新event的各項參數的合法性的判斷,我假設用戶輸入的一定是合法的
			addEvent(eventName, eventDescription, eventBeginDate, eventBeginTime, eventEndDate, eventEndTime, reminderMinutes); // 添加新event
		}
		else if (v == goBackButton) {
			goBack();
		}
	}

	@Override
	public void onFocusChange(View v, boolean hasFocus) {
		if (v == eventBeginDateText && hasFocus == true) {

			Calendar c = Calendar.getInstance();
			new DatePickerDialog(AddNewEventActivity.this,
					new DatePickerDialog.OnDateSetListener() {
						@Override
						public void onDateSet(DatePicker view, int year,
								int monthOfYear, int dayOfMonth) {
							eventBeginDateText.setText("開始日期:" + year + "-"
									+ (monthOfYear+1) + "-" + dayOfMonth);
							eventBeginDate[0] = year;
							eventBeginDate[1] = monthOfYear;
							eventBeginDate[2] = dayOfMonth;
						}
					}, c.get(Calendar.YEAR), c.get(Calendar.MONTH),
					c.get(Calendar.DAY_OF_MONTH)).show();

		} else if (v == eventBeginTimeText && hasFocus == true) {

			Calendar c = Calendar.getInstance();
			new TimePickerDialog(AddNewEventActivity.this,
					new TimePickerDialog.OnTimeSetListener() {
						@Override
						public void onTimeSet(TimePicker view, int hourOfDay,
								int minute) {
							eventBeginTimeText.setText("開始時間:" + hourOfDay
									+ "時" + minute + "分");
							eventBeginTime[0] = hourOfDay;
							eventBeginTime[1] = minute;
						}
					}, c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE),
					true).show();

		} else if (v == eventEndDateText && hasFocus == true) {

			Calendar c = Calendar.getInstance();
			new DatePickerDialog(AddNewEventActivity.this,
					new DatePickerDialog.OnDateSetListener() {
						@Override
						public void onDateSet(DatePicker view, int year,
								int monthOfYear, int dayOfMonth) {
							eventEndDateText.setText("結束日期:" + year + "-"
									+ (monthOfYear+1) + "-" + dayOfMonth);
							eventEndDate[0] = year;
							eventEndDate[1] = monthOfYear;
							eventEndDate[2] = dayOfMonth;
						}
					}, c.get(Calendar.YEAR), c.get(Calendar.MONTH),
					c.get(Calendar.DAY_OF_MONTH)).show();

		} else if (v == eventEndTimeText && hasFocus == true) {

			Calendar c = Calendar.getInstance();
			new TimePickerDialog(AddNewEventActivity.this,
					new TimePickerDialog.OnTimeSetListener() {
						@Override
						public void onTimeSet(TimePicker view, int hourOfDay,
								int minute) {
							eventEndTimeText.setText("結束時間:" + hourOfDay + "時"
									+ minute + "分");
 							eventEndTime[0] = hourOfDay;
 							eventEndTime[1] = minute;
						}
					}, c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE),
					true).show();

		}
	}

	private void addEvent(String eventName, String eventDescription,
			int eventBeginDate[], int eventBeginTime[], int eventEndDate[],
			int eventEndTime[], int reminderMinutus) {
		long calId = 1;
		long startMillis = 0;
		long endMillis = 0;
		Calendar beginTime = Calendar.getInstance();
		beginTime.set(eventBeginDate[0], eventBeginDate[1], eventBeginDate[2], eventBeginTime[0], eventBeginTime[1]); // 注意:月份系統會自動加1
		startMillis = beginTime.getTimeInMillis();
		Calendar endTime = Calendar.getInstance();
		endTime.set(eventEndDate[0], eventEndDate[1], eventEndDate[2], eventEndTime[0], eventEndTime[1]);
		endMillis = endTime.getTimeInMillis();

		ContentResolver cr = getContentResolver(); // 添加新event,步驟是固定的
		ContentValues values = new ContentValues();
		values.put(Events.DTSTART, startMillis);
		values.put(Events.DTEND, endMillis);
		values.put(Events.TITLE, eventName);
		values.put(Events.DESCRIPTION, eventDescription);
		values.put(Events.CALENDAR_ID, calId);
		values.put(Events.EVENT_TIMEZONE, "GMT+8");
		Uri uri = cr.insert(Events.CONTENT_URI, values);
		Long myEventsId = Long.parseLong(uri.getLastPathSegment()); // 獲取剛纔添加的event的Id

		ContentResolver cr1 = getContentResolver(); // 爲剛纔新添加的event添加reminder
		ContentValues values1 = new ContentValues();
		values1.put(Reminders.MINUTES, reminderMinutus);
		values1.put(Reminders.EVENT_ID, myEventsId);
		values1.put(Reminders.METHOD, Reminders.METHOD_ALERT);
		cr1.insert(Reminders.CONTENT_URI, values1); // 調用這個方法返回值是一個Uri

		setAlarmDeal(startMillis); // 設置reminder開始的時候,啓動另一個activity

		showMessageDialog("插入成功!" + "\n" + uri.getLastPathSegment() + "\n"
				+ uri.getAuthority());
	}

	private void setAlarmDeal(long time) { // 設置全局定時器
		Intent intent = new Intent(this, AlarmActivity.class);
		PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
		AlarmManager aManager = (AlarmManager) getSystemService(Service.ALARM_SERVICE);
		aManager.set(AlarmManager.RTC_WAKEUP, time, pi); // 當系統調用System.currentTimeMillis()方法返回值與time相同時啓動pi對應的組件
	}
	
	public void showMessageDialog(String info) { // 彈出消息對話框,消息的內容是info,且點擊此對話框的確定按鈕後會返回
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(info);
		builder.setTitle("information");
		builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				goBack(); 
			}
		});
		AlertDialog alert = builder.create();
		alert.show();
	}
	
	private void goBack() { // 返回
		Intent itent = new Intent();
		itent.setClass(AddNewEventActivity.this,
				AndroidCalendarProviderTestActivity.class);
		startActivity(itent);
		AddNewEventActivity.this.finish();
	}
}

下面是event發生時,同時啓動的那個Activity的代碼,當某個event發生,除了系統會有Notification的提醒,無論本Demo是否正在運行,手機都會啓動這個Activity,將手機設置成爲震動,代碼如下:

package org.ls;

import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.os.Bundle;

public class AlarmActivity extends Activity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.alarm_activity);
		
		setVibrate(); // 將手機情景模式設爲震動
	}
	
	private void setVibrate() {
		AudioManager audio = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
		audio.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
        audio.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_ON);
        audio.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION, AudioManager.VIBRATE_SETTING_ON);   
	}
}

相關的xml文件:

alarm_activity.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/alarminfo"
        android:id="@+id/displayinfo"
        />

</LinearLayout>


add_event.xml:


<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:id="@+id/add_new_event">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <EditText 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:hint="在此填寫新event的名字"
    	android:id="@+id/event_name"
    	android:selectAllOnFocus="true"
        />
    <EditText 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:hint="簡要描述新event"
    	android:id="@+id/event_description"
    	android:selectAllOnFocus="true"
        />

    <EditText 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:hint="點擊選擇開始日期"
    	android:id="@+id/select_begin_date"
    	android:selectAllOnFocus="true"
        />
	<EditText 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:hint="點擊選擇開始時間"
    	android:id="@+id/select_begin_time"
    	android:selectAllOnFocus="true"
        />
   <!--  
    <TextView 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:text="選擇新event的結束時間:"
        />
	-->
    <EditText 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:hint="點擊選擇結束日期"
    	android:id="@+id/select_end_date"
    	android:selectAllOnFocus="true"
        />
	<EditText 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:hint="點擊選擇結束時間"
    	android:id="@+id/select_end_time"
    	android:selectAllOnFocus="true"
        />

    <!--  
    <TextView 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:text="爲新event的添加reminder:"
        /> 
      -->

<!--  
    <TextView 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:text="新event提前多少分鐘提醒您:"
        />
 -->
     <EditText 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:hint="在此填寫新event提前多少分鐘提醒您:"
    	android:selectAllOnFocus="true"
    	android:id="@+id/reminder_minutes"
        />

    <Button 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:text="確定"
    	android:id="@+id/ok"
        />
    <Button 
        android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:text="返回"
    	android:id="@+id/goback"
        />

</LinearLayout>
</ScrollView>


main.xml:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

   <Button
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="查詢所有日曆"
    android:id="@+id/querycalendars"
       />
   <Button
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="添加新日曆項"
    android:id="@+id/addevents"
       />
   <Button
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="查詢所有event"
    android:id="@+id/queryevents"
       />
    <EditText 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:hint="在這裏輸入要刪除event的id"
    android:id="@+id/geteventid"
    />
     <Button
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="刪除該event"
    android:id="@+id/delevent"
       />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello"
        android:id="@+id/displayevents"
         />

</LinearLayout>

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.ls"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="14" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".AndroidCalendarProviderTestActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="AddNewEventActivity"></activity>
        <activity android:name="AlarmActivity"></activity>
    </application>

    <uses-permission android:name="android.permission.READ_CALENDAR"/>
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
</manifest>

另外記住,AlarmActivity一定要在AndroidManifest.xml中註冊,否則,到了event執行時,系統不但不會啓動AlarmActivity,甚至會練各種Log也不會打印;此外還有,Java中的月份是從0開始的,這一點很容易被忽略,一旦忽略會帶來很多匪夷所思的事情,也很讓人苦惱。

發佈了52 篇原創文章 · 獲贊 63 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章