2020年7月5日 星期日

從svn搬家到git上

前陣子有段時間跟另一個團隊合作開發一個專案
因為對方團隊的leader不願轉換到git
所以在交接程式給對方的過度期就需要不斷的把對方開發的程式先併入git再將程式提交給對方(其實併版完是可以直接merge回去的,但因為對方意見很多所以後來就直接匯出差異檔了)
不過上面都是題外話

重點是最近又有另一個專案要從svn搬過來
但偏偏幾個簡單的指令就是會忘記
所以這次就在這邊記錄一下

第一步-把svn的程式check out下來
git svn clone https://svn-server/MyProject
第二步-進入專案目錄
cd MyProject
第三步-加入git 位置,並提交
git remote add origin https://git-server/MyProject.git
git push origin master

這樣就成功把專案搬到git上了

2011年10月4日 星期二

Android修改system唯讀權限:remount

完整文章來源http://blog.csdn.net/lixinso/article/details/5835598

lixinso@lixinso-desktop:~$ adb shell
# mount
# mount -o remount /dev/block/mtdblock0 /system
# mount

mount完就可以任意修改删除拉~~~~


另一個更簡單的方法是直接
:~$adb remount

即可

2011年10月1日 星期六

將Google Appengine 的資料轉成 JSON格式輸出

將以下程式加入程式中
 
from google.appengine.ext import db
from google.appengine.ext.db import BadValueError
import datetime, time
from google.appengine.api import users

SIMPLE_TYPES = (int, long, float, bool, dict, basestring, list)

def to_dict(model):
    output = {}
    if isinstance(model, db.Query):
        output = []
        for v in model:
            output.append(to_dict(v))
        return output
    elif isinstance(model, list):
        output = []
        for v in model:
            output.append(to_dict(v))
        return output
 
    for key, prop in model.properties().iteritems():
        value = getattr(model, key)

        if value is None or isinstance(value, SIMPLE_TYPES):
            output[key] = value
        elif isinstance(value, datetime.date):
            output[key] = value.strftime("%Y/%m/%d %H:%M")
        elif isinstance(value, db.GeoPt):
            output[key] = {'lat': value.lat, 'lon': value.lon}
        elif isinstance(value, db.Model):
            output[key] = to_dict(value)
        elif isinstance(value, users.User):
            output = {}
            methods = ['nickname', 'email', 'auth_domain']
            for method in methods:
                output[method] = getattr(value, method)()
            return output  

        else:
            raise ValueError('cannot encode ' + repr(prop))
    return output

使用範例

import model


rooms= model.Room.all()
self.response.out.write(model.to_dict(rooms))

參考資料

GAE返回JSON数据
How to serialize db.Model objects to json
JSON serialization of Google App Engine models

2011年9月28日 星期三

[教學]用Facebook帳號登入你的網站

在開始之前...你必須先向facebook註冊你的網站

https://developers.facebook.com/



完成後即可得到你的

應用程式ID/API鑰匙=> 即後面會用到的client_id

網站URL=> 這應該是你自己設定的後面也會用到redirect_uri

應用程式密鑰=> 後面會用到的client_secret



完成註冊後就可以開始以下步驟了



Step1: 做登入的按鍵

這按鍵的只要加上這個超連結就行了

https://www.facebook.com/dialog/oauth?client_id=你的client_id&redirect_uri=http://www.7998.com.tw/



Step2: 在你的登入頁面需要加入一個code的參數 以便facebook將資料帶進來

在使用者按下登入的按鍵後facebook會讓使用者登入後再導回到你的網站並附帶一個code的參數


http://www.7998.com.tw/?code=2345eashdfhasdfjasdkfjasdlfjlasdj......這code是我亂打的 = ="



Step3: 利用facebook 傳來的code參數向facebook取得access_token

https://graph.facebook.com/oauth/access_token?client_id=應用程式ID/API鑰匙&redirect_uri=你的網址&client_secret=應用程式密鑰&code=2345eashdfhasdfjasdkfjasdlfjlasdj



會得到facebook 回傳的資料

access_token=asdfasdbja;ljserowjelrjlwjksejlfjsl....這當然也是我亂打的= ="



Step4: 利用access_token就可以取的使用者的資料了

https://graph.facebook.com/me?access_token=asdfasdbja;ljserowjelrjlwjksejlfjsl


詳細流程可以看facebook的官方說明
https://developers.facebook.com/docs/authentication/

2011年9月27日 星期二

[BCB] 視窗間傳遞物件訊息 SendMessage

在寫程式的時候有時候會需要和其他程式做溝通
這程式很有可能就在本機的電腦上的另一支程式
這時候就可以利用SendMessage這API來達成


首先先宣告結構
typedef struce _MYSTRUCT
{
char szChar[255];
int iInt;
}MyStruct;
在傳送端的部份

在.cpp中加入Send的function 當然最好在.h中先宣告
void Send()
{
AnsiString app_name = "要收到訊息的視窗";
AnsiString msg = "要傳送的訊息";
int type = 1; //要傳送的數字

HWND hWnd = FindWindow(NULL, app_name.c_str()); //找到視窗

if(hWnd)
{
MyStruct ms;
istrcpy(ms.szChar, msg.c_str());
ms.iInt=type;
COPYDATASTRUCT CopyData;
CopyData.dwData=0;
CopyData.cbData=sizeof(MyStruct);
CopyData.lpData=&ms;

SendMessage( hWnd, WM_COPYDATA, NULL, (LPARM)&CopyData);

}
}


在接受端的部份
在from.h的private:後面加入宣告

void __fastcall WMCopyData( TMessage &Message );

BEGIN_MESSGE_MAP
MESSAGE_HANDLER(WM_COPYDATA, TMessage, WMCopyData)
END_MESSAGE_MAP(TForm)

在.cpp中加入
void __fastcall TMainForm::WMCopyData(TMessage &Message)
{
COPYDATASTRUCT *CopyData = (COPYDATASTRUCT*) (Message.LParam);
if(CopyData->cbData == sizeof(MyStruct) )
{
MyStruct ms;
CopyMemory(&ms, CopyData->lpData, CopyData->cbData);
//ms.Int 即是接收到的數字
//ms.szChar即是要接收到的訊息
}
}

以上資料是從Delphi.Ktop找到的

2011年7月22日 星期五

7998住宿網

最近完成了一個網站架在Google的服務上, 提供日租訂房的服務,可提供日租套房,民宿等訂房服務。如果有房東看到這篇可以來試試看這個系統





網址:http://www.7998.com.tw/

2011年2月23日 星期三

Qt 動態載入 DLL

在Qt中要動態載入DLL檔可以用QLibrary來載入
首先

#include < QLibrary >
定義Function
typedef void (*Function_Name)(int 參數1,int 參數2 , ...);

然後在程式中載入的方法是

QLibrary testlib("DLL_Name"); //此處DLL_Name不用加.dll

if(test_lib.load())//載入dll並判斷是否成功
{
qDebug()<<"load dll ok.";
//宣告Function(DLL_Function_Name為DLL檔裡定義的Function名稱)
Function_Name test_function = (Function_Name)test_lib.resolve("DLL_Function_Name");
//現在可以使用Function了
if(test_function)
{
int a = 0;
int b = 0;

test_function( a, b );
}
}else{
qDebug()<<"load dll fail.";
}

2011年2月9日 星期三

Qt 4.7 Tcp Socket Client 教學範例

首先在專案的.pro檔中要先加入
QT += network

接著在程式.h檔中加入

#include < QtNetwork/QTcpSocket >

//宣告一個QTcpSocket方便在整個程式中使用
QTcpSocket *m_socket;


在程式.cpp裡

//產生QTcpSocket物件
m_socket = new QTcpSocket(this);

//Connect事件觸發的Function
//在收到Server的訊息時會觸發readRead()
connect(m_socket,SIGNAL(readyRead()),this,SLOT(slotReadyRead()));
//連線成功的事件
connect(m_socket,SIGNAL(connected()),this,SLOT(slotConnected()));
//斷線的事件
connect(m_socket,SIGNAL(disconnected()),this,SLOT(slotDisConnected()));

//連線到Server
QString ip_address="127.0.0.1";
int port = 2266
m_socket->connectToHost(ip_address,port );


//傳送訊息
QTextStream stream(m_socket);
stream << "Server: Hi, I am client";

//接收訊息
m_socket->readAll();



2011年1月11日 星期二

Android Service 定時自動執行

在Android讓widget自動更新其實可以直接寫在widget Provider的onUpdate裡就行了
但是後面的版本並不能設定update的時間,他已經被設定成30分鐘更新一次
所以如果要讓widget自動更新比較好的做法事建立一個Service並註冊一個AlarmManager設定定時執行的間隔時間
以下為範例
在Service中定義一個PendngIntent

public static PendingIntent serviceIntent = null;

在Service中定義註冊AlarmManager的Function

public static void registerService(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

//如果serviceIntent不為null(已註冊過)
if (serviceIntent != null)
alarmManager.cancel(serviceIntent); //清除

final int updateInterval = 60 * 60000;//間隔時間單位為ms

//間隔時間不為0
if (updateInterval != 0) {
//如果serviceIntent為null

if (serviceIntent == null) {
//建立intent
Intent intent = new Intent(context, 要更新的Service.class);
//建立serviceIntent
serviceIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
//在AlarmManager設定重覆執行的Server的intent
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + updateInterval,
updateInterval, serviceIntent);
}
}

在Service中定義取消AlarmManager註冊

public static void removeService(Context context) {
if (serviceIntent != null) {
((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).cancel(serviceIntent);
serviceIntent = null;
}
}


最後在Widget實作onEnabled和onDisabled兩個Function
各別在裡面呼叫registerService和removeService即可
如

@Override
public void onDisabled(Context context) {
// TODO Auto-generated method stub
UpdateService.removeService(context);

super.onDisabled(context);
}

@Override
public void onEnabled(Context context) {
// TODO Auto-generated method stub
UpdateService.registerService(context);
super.onEnabled(context);
}

2010年12月24日 星期五

Android EditText的輸入事件

關於Android的EditText的輸入事件,一開始我以為是用OnKeyListener去處理就可以了。
後來發現我錯了...OnKeyListener只接收"實體鍵盤的event觸發"對一般Android都是觸控的虛擬鍵盤一點反應都沒有。Google後發現應該是要用addTextChangedListener來處理才是正確的做法
程式大致如下:

myEditText.addTextChangedListener(new TextWatcher(){
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub

}});

裡面三個function是new TextWatcher()必須要實作的
程式寫在onTextChange()那function裡面就可以了

2010年12月14日 星期二

Yahoo 搜尋股票代號API

在輸入股票代號時常常會不知道公司的股票代號
這時就可以用Yahoo 的這個API來搜尋

使用方式如下
http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=關鍵字&callback=YAHOO.Finance.SymbolSuggest.ssCallback

此API可以尋找各交易所的股票代號相當的方便
但因為資料都是英文所以要搜尋中文公司也要輸入英文的關鍵字才行

用關鍵字Yahoo搜尋的結果如下
YAHOO.Finance.SymbolSuggest.ssCallback({"ResultSet":{"Query":"yahoo","Result":[{"symbol":"YHOO","name": "Yahoo! Inc.","exch": "NMS","type": "S","exchDisp":"NASDAQ","typeDisp":"Equity"},{"symbol":"YOJ.F","name": "YAHOO JAPAN","exch": "FRA","type": "S","exchDisp":"Frankfurt","typeDisp":"Equity"},{"symbol":"YOJ.BE","name": "YAHOO JAPAN","exch": "BER","type": "S","exchDisp":"Berlin","typeDisp":"Equity"},{"symbol":"YHO.MU","name": "YAHOO","exch": "MUN","type": "S","exchDisp":"Munich","typeDisp":"Equity"},{"symbol":"YHO.F","name": "YAHOO","exch": "FRA","type": "S","exchDisp":"Frankfurt","typeDisp":"Equity"},{"symbol":"YAHOF.PK","name": "YAHOO JAPAN CORP","exch": "PNK","type": "S","exchDisp":"Pink Sheets","typeDisp":"Equity"},{"symbol":"ETD","name": "Citigroup Inc. ELKS On Yahoo","exch": "PCX","type": "S","typeDisp":"Equity"},{"symbol":"YHO.DU","name": "YAHOO","exch": "DUS","type": "S","exchDisp":"Dusseldorf Stock Exchange","typeDisp":"Equity"},{"symbol":"YOJ.DE","name": "YAHOO JAPAN","exch": "GER","type": "S","exchDisp":"XETRA","typeDisp":"Equity"},{"symbol":"YHO.HM","name": "YAHOO","exch": "HAM","type": "S","exchDisp":"Hamburg","typeDisp":"Equity"}]}})

和Google Stock Api一樣...也是JSON格式
symbol = 代號
name = 公司名稱
exch = 證券交易所
type = 應該是上市上櫃分別
exchDisp = 交易所地點

參考自
http://stackoverflow.com/questions/885456/stock-ticker-symbol-lookup-api&rurl=translate.google.com.tw&twu=1&usg=ALkJrhgoUpKv7sDtcpKatP_oy50z7GI2Jg

2010年12月2日 星期四

Android Http Get 實作範例

首先
在AndroidManifest.xml中要加入可以使用網路的權限
< uses-permission android:name="android.permission.INTERNET" >< /uses-permission >

在程式部份

//for Http Get
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;


public void executeHttpGet() throws Exception {
try {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(網址);
HttpResponse response = client.execute(request);
String retSrc = EntityUtils.toString(response.getEntity());

System.out.println(retSrc);
} finally {
}
}

Android SharedPreferences 儲存簡單的欄位資訊

Android 提供了 SharedPreferences 這個介面讓我們方便存取一些預設資料或是一些簡單的使用者輸入的欄位資訊
要使用這個介面第一步當然是
import android.content.SharedPreferences;

接著,就是程式碼的部份

首先介紹儲存資料的部份
//取得SharedPreferences物件 (參數一是偏好設定檔的名稱,參數二是讀取權限)
SharedPreferences pref = getSharedPreferences("PREF_STOCK", MODE_WORLD_WRITEABLE);
//要修改偏好設定檔必須透過一個SharedPreferences.Editor 物件
//取得SharedPreferences.Editor 物件
SharedPreferences.Editor prefEdt = pref.edit();
//寫入資料(參數一是欄位名稱,參數二是要寫入的資料)
prefEdt.putString("PREF_T", "hello world");
//最後一定要commit將資料寫入檔案
prefEdt.commit();


在讀取方面就簡單多了

//取得SharedPreferences物件 (參數一是偏好設定檔的名稱,參數二是讀取權限)
SharedPreferences pref = getSharedPreferences("PREF_STOCK", MODE_WORLD_WRITEABLE);
//取得資料 (參數一是欄位名稱,參數二是讀取失敗時的預設資料)
String getS = pref.getString("PREF_T", "");


以上就是讀寫一個偏好設定檔要用的功能了
其他更深入的說明介紹可以參考以下的資料
http://asia.edu.tw/~lincyu/Android/Chapter11.pdf

http://developer.android.com/reference/android/content/SharedPreferences.html

Android 讀取JSON使用範例

在Android中使用JSON其實滿方便的,因為Libary已經有寫好了,只要直接拿來用就好了
首先

import org.json.JSONObject;
import org.json.JSONArray;

然後假設JSON格式的資料在一個字串json_data中
如果資料最外層是[]那就是JSONArray
最外層是{}則是JSONObject

以上一篇從Google取得的股票資料為例
最外層是[]然後裡面有不同的物件
取得資料方式如下

//將資料寫入JSONArray
JSONArray result = new JSONArray(json_data);
//取出陣列內所有物件
for(int i = 0;i < result.length(); i++)
{
//取出JSON物件
JSONObject stock_data = result.getJSONObject(i);
//取得物件內資料
System.out.println("t:"+stock_data.getString("t"));
System.out.println("l_cur:"+stock_data.getString("l_cur"));
System.out.println("c:"+stock_data.getString("c"));
System.out.println("cp:"+stock_data.getString("cp"));
}



可參考API網址
http://developer.android.com/reference/org/json/package-summary.html

2010年12月1日 星期三

Google Stock 股市API

跟據
http://googlefinanceblog.blogspot.com/2008/04/taiwan-stock-exchange-pricing-data.html
可以得知在2008Google的Stock API就已經有台灣股市的資料了使用方式就是把後面改成
TPE:代號 或是 代號.TW

查詢方式如下:(以2454聯發科)為例
http://finance.google.com/finance/info?client=ig&q=TPE:2454

得到的結果
// [ { "id": "683538" ,"t" : "2454" ,"e" : "TPE" ,"l" : "391.50" ,"l_cur" : "NT$391.50" ,"ltt":"1:30PM Taipei" ,"lt" : "Dec 1, 1:30PM Taipei" ,"c" : "+1.00" ,"cp" : "0.26" ,"ccol" : "chg" } ]

看得出來是個JSON格式的file
t就是代號
"l_cur":成交價格
"ltt":時間
"lt":日期時間
"c":漲跌
"cp":漲跌幅


其他資訊可以參考
http://stackoverflow.com/questions/527703/google-financial-api-how-get-stock-quotes

Google Finance API docs
http://code.google.com/intl/zh-TW/apis/finance/docs/2.0/reference.html

2010年11月26日 星期五

Android Bitmap 存檔


import java.io.File;
import java.io.FileOutputStream;
import java.io.BufferedOutputStream;


File myDrawFile = new File(mSaveFilePath);
try {
BufferedOutputStream bos = new BufferedOutputStream
(new FileOutputStream(myDrawFile));
mBitmap.compress(Bitmap.CompressFormat.PNG, 90, bos);
bos.flush();
bos.close();

} catch (Exception e) {
e.printStackTrace();
Log.d(null, "Save file error!");
return false;
}
Log.d(null, "Save file ok!");
return true;

2010年11月24日 星期三

[python] Google app engine 登出功能

from google.appengine.api import users

#利用users api取得登出網址(後面的參數是登出後要前往的頁面)
logoutUrl = users.create_logout_url("/")

2010年11月9日 星期二

Android初體驗之編譯出xxx.out.xml的錯誤

在寫Android 的時候有時候會發生出現xxx.out.xml的錯誤
這種錯誤的解決方法是

1.在Project->Clean清除目前的編譯
2.從專案中刪除xxx.out.xml
3.重新編譯

這問題發生的原因是:在Eclipse中編輯XML檔案,會預設用XSLT來轉換文件
所以當我們要執行編譯時,要把焦點由XML移開到專案上
為了必免這個問題可以參考以下做法


可以在Eclipse設定,選單Windows->Preference,選擇節點Run/Debug->Lauching,Lauch Operation選擇第一項。





這樣就不用每次都要把Focus 移開XML文件。

參考如下:
http://programmersay.blogspot.com/2010/07/android-mainoutxml.html
http://www.cnblogs.com/chunhui588/archive/2010/06/26/Android-debug-main-out-xml-parsing-error.html

2010年8月23日 星期一

C++ 使用環境變數

在Linux中有時候需要知道一些環境變數
例如要知道使用者的家目錄位置等。
這時候就可以利用getenv這個function
以下以Qt的程式碼示範

#include < stdlib.h >

QString strEnv = getenv( "HOME");

2010年7月28日 星期三