2012年1月15日 星期日

在其位,謀其政

台灣大選又走過了一遭了。幾天前參加單位的活動,看著路邊插著的旗幟,才想起來這周末有大選,想著想著,好像期待發生啥事,但事實證明,無論誰選上了總統,日子還是一樣要過的,就像酒醒過後發現一項責任都沒少過。整體上我還滿不喜歡參與政治活動,政治是一種意念,只要你擁有了一方,碰到相反的另一方時,很容易起磨擦,這是無法避免的,而我喜歡自然界的定律,用亂度來達成平衡,無為而治也挺不賴的(跟碩班老師聊時,反而被說還是要多少扛起社會責任才是 XD)  網路上有很多各候選人的負面消息,我覺得都很中肯,只是這絕對不是誰當選誰下台就能解決的。


最近對生活體驗不少,記著以前總是很佩服 xxx 怎會想到 ooo 的念頭,這幾年漸漸發現,那只不過是在某個位置上就會順水推舟的看到的事情。所以啊,最重要的還是想想自己想要付出甚麼來豐富青春吧!這幾天還滿羨慕同事特地請假當志工呢!身體力行地支持心中的候選人。希望,今年也能找到一個目標,好好地衝刺一番。


2012年1月12日 星期四

Android 開發筆記 - 取得 Calendar Events 與相關筆記

最近摸到一台變形金剛,順便學習一些簡單的東西,這次目標就是取得 Calendar Events,對整個 Android 系統來說,有不少 App 都提供讓人存取的功能,在此以 Calendar 為例。


另外一提的,很多資料都是用 SQLite 格式儲存在系統裡頭,可以透過 DDMS 或其他 shell 方式瀏覽或取出 db 檔案(/data/data/com.android.providers.calendar/databases/calendar.db),接著可以用 Firefox Plugin - SQLite Manager 去查看也挺方便喔。(此動作需要root權限)


程式碼:


package tw.study.provider.calendar;


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


import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.util.Log;


public class CalendarEventProviderActivity extends Activity {
    /** Called when the activity is first created. */
    private String tagReport = "CalendarProviderActivity";
    private ArrayList<String> calendarEvents = new ArrayList<String>();
    private Hashtable<String,String> accountInfo = new Hashtable<String,String>();
    private String URI_CALENDAR_BASE = "content://com.android.calendar/calendars";
    private String URI_CALENDAR_RANGE_QUERY = "content://com.android.calendar/instances/when"; // content://com.android.calendar/instances/when/begin/end
    private SimpleDateFormat TimeFormat = new SimpleDateFormat("HH:mm");

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        if(getInfoFromCalendarDB()>0) {
                // do something via calendarEvents
        }
    }

    private int getInfoFromCalendarDB() {
        long dateRangeBegin = new Date().getTime();
        Date today = new Date(dateRangeBegin + DateUtils.DAY_IN_MILLIS);
        long dateRangeEnd=new Date(today.getYear(),today.getMonth(),today.getDate()).getTime();
        
        Log.e(tagReport,"date range from '"+dateRangeBegin +"' to '"+dateRangeEnd+"'");

        ContentResolver contentResolver = this.getContentResolver();
        Cursor accountInfoCursor = contentResolver.query(Uri.parse(URI_CALENDAR_BASE), (new String[] { "_id", "displayName", "selected", "_sync_account" }), null, null, null);
        while (accountInfoCursor.moveToNext()) {
            String _id = accountInfoCursor.getString(0);
            String displayName = accountInfoCursor.getString(1);
            String syncAccount = accountInfoCursor.getString(3);
            if( !accountInfoCursor.getString(2).equals("0") ) { // selected => enable
                accountInfo.put( syncAccount, displayName ); // use for check or display the account name
                accountInfo.put( _id, displayName );
            }
        }

        // show all columns
        String targetQuery = URI_CALENDAR_RANGE_QUERY+"/"+dateRangeBegin+"/"+dateRangeEnd;
        Log.e(tagReport,"Range Query:"+targetQuery);
        Cursor eventCursor = contentResolver.query(Uri.parse(targetQuery), null, null, null, "startDay ASC, startMinute ASC");
        for( String c : eventCursor.getColumnNames() ) 
            Log.e(tagReport,"column name:"+c);

        // add all events
        calendarEvents.clear();
        eventCursor = contentResolver.query(Uri.parse(URI_CALENDAR_RANGE_QUERY+"/"+dateRangeBegin+"/"+dateRangeEnd), new String[] { "title", "begin", "end", "calendar_id"}, null,null,"startDay ASC, startMinute ASC");
        while (eventCursor.moveToNext()) {
            String title = eventCursor.getString(0);
            Long begin = eventCursor.getLong(1);
            Long end = eventCursor.getLong(2);
            String accountId = eventCursor.getString(3);
                if( accountInfo.containsKey(accountId) ) { // skip the account which is not enabled
                calendarEvents.add("["+TimeFormat.format(new Date(begin))+"-"+TimeFormat.format(new Date(end))+"] "+title+"("+accountInfo.get(accountId)+")" );
            }
        }
        return calendarEvents.size();
    }


AndroidManifest.xml:


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


輸出:


date range from '1326368807153' to '1326384000000'
Range Query:content://com.android.calendar/instances/when/1326368807153/1326384000000
column name:originalEvent
column name:ownerAccount
column name:endDay
column name:visibility
column name:endMinute
column name:rrule
column name:event_id
column name:lastDate
column name:hasAlarm
column name:guestsCanModify
column name:transparency
column name:rdate
column name:exrule
column name:guestsCanSeeGuests
column name:title
column name:dtstart
column name:selected
column name:timezone
column name:_id
column name:hasAttendeeData
column name:commentsUri
column name:startDay
column name:description
column name:htmlUri
column name:end
column name:startMinute
column name:hasExtendedProperties
column name:calendar_id
column name:eventLocation
column name:dtend
column name:access_level
column name:allDay
column name:organizer
column name:originalAllDay
column name:deleted
column name:url
column name:begin
column name:originalInstanceTime
column name:duration
column name:color
column name:selfAttendeeStatus
column name:guestsCanInviteOthers
column name:exdate
column name:eventStatus
column name:eventTimezone


2012年1月6日 星期五

[Linux] 忘記密碼、更新 root 密碼的處理 @ Ubuntu 11.10

前陣子接手案子,但同事離職前程式碼沒有交接清楚,所以我就稍微黑一下前同事的桌機了 XD 提到破解密碼,過去總有一些電影場景,厲害的黑客在黑幫老大的壓力下(或正妹的服務下),只靠一台筆電跟網路就突破哪台銀行主機等等的,說真的還滿誇張的,最近則看了不可能的任務四,發現內容越來越寫實,真正的破解方式就是要到主機身邊給他本體入侵一下啦!


所以,其實忘記密碼或是想要強行入侵,只要在本機端就可以了 :P 過去我只有用過 FreeBSD 的 Single User Mode 啦,這次算是體驗一下 Ubuntu/Linux 環境:



  1. 重開機進入 Single User Mode (Recovery Mode)

  2. 用 root 將 FS 狀態改寫成可讀寫


    • $ mount -o remount-rw /


  3. 強制更換密碼


    • $ passwd your_id



這次就完成了 XD 比較可能卡住的是第一步跟第二步,像我就搞不懂怎樣進入 Single User Mode。另外,將檔案系統改成可讀寫後,修改的帳密才會儲存起來。最後,我就只是單純地把前輩的密碼換掉,再用他的帳號登入而已 :P 事實也證明,不要以為有帳密管理就安全,一旦主機暴露出來還是一樣很危險。目前我還沒學會的是處理 Windows 系統的部分。

2011年12月28日 星期三

明天的事?就交給明天來煩惱!


工作告一個段落了。今年意外接了兩位前輩的離職工作,原先我已經被分配全時做某個工作了,接了別人離職的工作,等同被加了 2 個人以上的工作量,這真的不是件好事。慶幸的,最後我也走出陰霾。


經過這次體驗,讓我學到不少事,例如經歷一些行政精華啊,也從中強化一些意志,算起來也稱得上大收穫囉 :D


2011年12月18日 星期日

2011-12-31前,記得辦一下中華電信「我的熱線」

前陣子收到不少網路文章,說中華電信在衝市占率?2011年底前申辦「我的熱線」可以享用一組免設定費,且24個月免月租費的服務。


然而,一堆文章都只提到"免設定費"、"免月租費"的訊息,那我在 emome 網站上卻看到"我的熱線"其實是以秒計費的,所以很擔心這只是文字噱頭,最後打電話問客服小姐,才確定這是 2011-11-01 至 2011-12-31 期間,申辦的優惠方案可以"免通話費"喔。目前優惠方案是設定第一組免設定費、免月租費的,假設你的門號設定兩組,那第一組免設定免月租,第二組則是要設定費 50 元且每個月都要 50 元月租費,同理第三、第四和第五組,都是要收月租費跟設定費的。所以,至少去設定一組吧!兩年內打電話都不用錢,何樂而不為?


簡言之,在 2011-12-31 前,到中華電信服務中心攜帶"雙證件"辦理「我的熱線」,可享有一組熱線號碼 24 個月完全免費(免設定費、免月租費、免通話費)。假設是在 2011-12-17 時,A門號設定打給 B 後,過不久就會收到系統寄來的簡訊,接著在 2013-12-17(18?) 前,從 A 打給 B 都是免費的。


這麼好的大放送,記得去辦一下啊。有任何問題可以用手機播打 0800-080-123 詢問客服人員,另外,CHT 週六、日營業服務據點可以參考一下,我是挑服務中心而不是特約的,有問題可以先問看看特約店是不是可以辦理。


相關連結: