2012年12月17日 星期一

Note10

package com.example.upload;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
//import android.util.Base64;
import com.example.upload.Base64;

import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.io.Reader;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main extends Activity {
    private static final int SELECT_PICTURE = 1;
        private String selectedImagePath;
        private ImageView img;
        
        //EditText ed=(EditText)findViewById(R.id.ed);
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            img = (ImageView)findViewById(R.id.ImageView01);
            ((Button) findViewById(R.id.Button01)).setOnClickListener(new OnClickListener()
            {
                public void onClick(View arg0) 
                {
                    //選擇圖片
                    Intent intent = new Intent();
                    intent.setType("image/*");
                    intent.setAction(Intent.ACTION_GET_CONTENT);
                    startActivityForResult(Intent.createChooser(intent,"Select Picture"), SELECT_PICTURE);
                    //最後一個參數傳入選擇圖片的URI
                }
            });
        }
        public void onActivityResult(int requestCode, int resultCode, Intent data) 
        {
            InputStream is;
            //data去接剛剛選取的圖片
            if (resultCode == RESULT_OK) 
            {
                if (requestCode == SELECT_PICTURE) 
                {
                    //取得路徑
                    Uri selectedImageUri = data.getData();
                    selectedImagePath = getPath(selectedImageUri);
                    System.out.println("Image Path : " + selectedImagePath);
                    
                    //設定顯示圖片
                    img.setImageURI(selectedImageUri);
                    //使用Bitmap取圖片
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inSampleSize = 2;
                    //圖片寬高都為原來的二分之一,即圖片為原來的四分之一
                    Bitmap bitmap = BitmapFactory.decodeFile(selectedImagePath,options);    
                    ByteArrayOutputStream bao = new ByteArrayOutputStream();
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 90, bao);
                    byte [] ba = bao.toByteArray();
                    //要POST至PHP檔使用Base64編碼
                    String ba1=Base64.encodeBytes(ba);
                    final ArrayList<NameValuePair> nameValuePairs = new
                    ArrayList<NameValuePair>();
                    nameValuePairs.add(new BasicNameValuePair("source",ba1));
                    try{
                        /*
                            HttpClient httpclient = new DefaultHttpClient();
                            HttpPost httppost = new
                            HttpPost("http://127.0.0.1/SOT/upload.php");
                            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                            HttpResponse response = httpclient.execute(httppost);
                            HttpEntity entity = response.getEntity();
                            is = entity.getContent();
                        */
                        //好像都不能直接跑在主執行緒上因此直接做了Thread讓他去用
                        Thread thread = new Thread(){ 
                            @Override
                            public void run(){ 
                                try{
                                    HttpClient httpclient = new DefaultHttpClient();
                                    HttpPost httppost = new
                                    HttpPost("YOUR_URL");
                                    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));
                                    //設定輸出為UTF-8
                                    HttpResponse response = httpclient.execute(httppost);
                                    HttpEntity entity = response.getEntity();
                                    InputStream is = entity.getContent();

                                }catch (Exception e){
                                    e.printStackTrace();
                                }finally{
                                }
                            }
                        };
                        //開始執行執行緒
                        thread.start();
                    }catch(Exception e){
                        Log.e("log_tag", "Error in http connection "+e.toString());
                    }
    
                }
            }
        }
        public String getPath(Uri uri) 
        {    String[] projection = 
            {
                MediaStore.Images.Media.DATA 
            };
            Cursor cursor = managedQuery(uri, projection, null, null, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }
        
        
        
        
        
         public String convertStreamToString(InputStream is)
                    throws IOException {
                //
                // To convert the InputStream to String we use the
                // Reader.read(char[] buffer) method. We iterate until the
                // Reader return -1 which means there's no more data to
                // read. We use the StringWriter class to produce the string.
                //
                if (is != null) {
                    Writer writer = new StringWriter();
         
                    char[] buffer = new char[1024];
                    try {
                        Reader reader = new BufferedReader(
                                new InputStreamReader(is, "UTF-8"));
                        int n;
                        while ((n = reader.read(buffer)) != -1) {
                            writer.write(buffer, 0, n);
                        }
                    } finally {
                        is.close();
                    }
                    return writer.toString();
                } else {        
                    return "";
                }
            }
}


PHP檔如下:




$base=$_REQUEST['source'];

echo $base;

// base64 encoded utf-8 string

$binary=base64_decode($base);

// binary, utf-8 bytes

header('Content-Type: bitmap; charset=utf-8');


$name=uniqid();
//uniqid()是用來亂數產生一串英文數字

$file = fopen("$name.jpg", 'wb');
//開啟以那串英文數字為檔名的檔案
fwrite($file, $binary);
//寫入檔案
fclose($file);
//寫入完畢關閉檔案

//unlink($file)
//unlink刪除檔案
echo "";




大部分的解釋都直接註解在裡面了

這是一個從Android選取圖片直接上傳到PHP的程式

花了不少時間拼拼湊湊才把這個弄出來

網路上資料雖然很多,但是很多都是不能用的,不然就是舊的...

以上的流程大概就是
Android -> choose image -> encode(use Base64) -> PHP($_REQUEST) -> decode(Base64) ->Write to File and save


下面這兩行是因為手機似乎不像電腦有那麼大的記憶體

如果不縮小一點常常都會出現java.lang.outmemory然後就直接Shutdown了...

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;


然後

httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));

如果要傳中文進去php檔必須要記得php檔要用utf儲存

android端送出資料的時候也要記得加上HTTP.UTF_8

如果出現這一行

org.apache.http.conn.HttpHostConnectException: Connection to http://127.0.0.1 refused

上網google似乎是因為android把自己當作local端了..

所以只要用 cmd ipconfig 查詢本機的ip換上去就可以了通常是 192.168.xxx.xxx

2012年10月7日 星期日

Note9



function test(str)
{
if (str=="")
  {
  document.getElementById("txtHint").innerHTML="";
  return;
  }
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
    }
  }
xmlhttp.open("GET","Check_ID.php?id="+str,true);
xmlhttp.send();
}


這次用了ajax利用GET把值傳到php檔來進行資料庫的判斷,

上面的是判斷瀏覽器所使用的,這是網路上的範例,只做了小部分的修改,

之後在想想能否再用上ajax的技術,不用整個畫面重新整理還蠻方便的,

接下來要做的是上學期驗收老師所提的功能,讓使用者能夠用圖片來進行發文的動作,

之前有看過文件Facebook是可以的,plurk跟twitter的文件還沒有去看。

2012年6月10日 星期日

Note8

上禮拜終於結束了專題的報告,

運氣很好的我果然還是被抽上台了,

報告的時候有點小緊張,

不過在發現老師好像大多在研究手中的那張A4之後,

就開始不那麼緊張了,

最後發問的時候雖然一直聽不懂老師在說什麼,

不過在休息時間在去問了幾次才聽懂,

老師的建議也很好,我應該再試試看能不能把圖片的資料也顯示出來,

這樣應該會更有吸引力。

接下來測試社群網站的未讀功能,

plurk和facebook看官方的文件是有未讀的可以使用,

但是Twitter似乎沒有提供這個功能,

可能還要在嘗試看看,

也開始規劃暑假應該做哪些進度,

忙碌的暑假。

2012年5月30日 星期三

Note7

這兩個禮拜幾乎都在撰寫文件,一直在新增修改,並對報告做演練,只是常常會遇到不知道該

怎麼寫的,比如系統架構圖,有些就是畫得很順,但是講起來就是不通。


2012年5月13日 星期日

Note6

這次先使用 plurk 做測試

$plurk->callAPI('/APP/Timeline/getUnreadPlurks');

回傳的是 object 的資料型態,我將他轉成Array方便使用,$b=objectToArray($json);



function objectToArray($d) {

if (is_array($d)) {
/*
* Return array converted to object
* Using __FUNCTION__ (Magic constant)
* for recursive call
*/
return array_map(__FUNCTION__, $d);

}

他會分別將帳戶分為兩個陣列然後一直包下去,第一個陣列放的是在這次撈出來的資料中,

有出現的使用者,包含暱稱、姓名、生日等等一些公開的基本資料,第二個陣列放的就是發

文的資料,但是第二個陣列裡面放的卻只有使用者的ID,因此如果要知道是哪一個使用者發

文的就必須要和第一個陣列做比對,才能取出發文者的資料,經過排列整理之後就能夠依照

自己的方式把他排好。我的方式是先將所有的id和該id的暱稱存放到一個陣列,當開始處理第

二個陣列(發文的資料)的時候,就到這一個陣列來比對該id是對應到哪一個暱稱。


例如:

xxx Says : [科普]  (小雨為什麼後悔了?) "

現在遇到的問題是因為都必須在到第一個陣列去做比對,但是有些人有暱稱,有些人沒有,從

朋友的塗鴉牆撈我作測試的帳號,卻無法正確的撈出暱稱,除了我的帳號之外其他人的顯示都是正常的目前還是不知道原因出在哪裡

2012年4月29日 星期日

Note5

終於考完期中考了

也因為期中考進度沒很多

這次把三個CODE整合起來

<form action="post.php" method="POST">
<input type="text" name="message"></input>
<input name="submit" type="submit" value="送出至三個社群網站"></input>
</form>

簡單的用html先做了文字方塊輸入要傳送的文字,用POST送出,然後把三段不同的社群網站的

CODE串在一起,註解真的蠻重要的,還有設變數的時候也是,一開始很擔心把三個一起輸入之

後會造成變數衝的到問題,但是遇到的都是一些小問題,很快的就解決了。



接下來要嘗試把未讀取的訊息撈出來。

2012年4月15日 星期日

Note4

終於把三個社群網站的驗證都做完了,接著驗證完成之後就可以開始做發文的動作,接下來為

了要讓使用者可以發文所以簡單的用了資料庫做了一個會員系統,讓使用者在註冊之後經過授

權之後會將之前處理好的token存入資料庫,如此一來只要使用者登入進來就可以從資料庫讀取

token進行發文的動作,這次是先將各個社群網站的發文分開,確定使用者可以透過此平台發布

之後,才將三個整合起來,

寫入資料庫以twitter舉例:

之前說選擇了tmhOauth這個library,在auth.php這個上面先加上連入資料庫的程式碼

<?php

session_start();

include("../../mysql_connect.inc.php");

$id = $_SESSION['id'];

?>

利用SESSION來傳遞用來識別使用者,TWITTER做完OAUTH回傳的會是這個

$_SESSION['access_token'],但是包了兩層token跟token_secret在下一層,分別是

$_SESSION['access_token']['oauth_token'];
$_SESSION['access_token']['oauth_token_secret'];

最後在下一段sql語法把這兩個值存進去資料庫就可以了。




貼文的部分也和上面一樣最上面也是加入連入資料庫的程式碼,

tmhOAUTH的發文是TWEET.PHP 如果要發佈英文以外的話要先將檔案編成utf8否則會變成亂

碼,之後下一段sql把token跟token_secret從資料庫取出,傳入php就可以跑了

$tmhOAuth = new tmhOAuth(array(
  'consumer_key' => 'your_key',
  'consumer_secret' => ' your_secret',

  'user_token' => 從資料庫抓取出來的token,
  'user_secret' => 從資料庫抓取出來的secret,

));

$code = $tmhOAuth->request('POST', $tmhOAuth->url('1/statuses/update'), array(
'status' => $message
));




下一次要把三個社群網站的發文合成一段。













2012年4月1日 星期日

運動

3/29 地點:虎科大操場 慢跑 
時間:17:00~17:50

Note3

這禮拜終於把 twitter 和 plurk 的驗證部分做完了,

OAuth的驗證過程在社群網站都會有提示





這個是twitter的流程,分成三個步驟:
1.Request token  https://api.twitter.com/oauth/request_token 流程和這串網址要求成功後會回傳幾個參數,但是只有oauth_token和oauth_token_secret在後面會使用到。

2.Authorize 拿到oauth_token之後必須將使用者導向https://api.twitter.com/oauth/authorize?oauth_token=  並且使用者同意之後便會回傳oauth_token及oauth_verifier並導向第一個步驟傳給伺服器的call_back網址。

3.Access_token  利用oauth_token及oauth_verifier向Access_token https://api.twitter.com/oauth/access_token 的網址要求,最後轉換成oauth_token及oauth_token_secret就完成了。


Twitter我選擇了 TmhOAuth 這個library,

首先到example裡面的auth.php裡面把Consumer Key及Consumer Secret填上,到伺服器上面去執

行之後進入 Sign in with Twitter 這個連結,待使用者授權後導回同一個網頁之後,oauth_token

和oauth_token_secret會在$_SESSION['access_token']這個陣列裡面取出來之後,填到tweet.php裡

面就可以做發布的動作,利用這組access_token可以做其他的事情,可以參考twitter 的網頁

https://dev.twitter.com/docs/api

Plurk方面沒得選..只有 plurkoauth https://github.com/clsung/plurkoauth ,

但是在這個library裡面我真的不會使用,他oauth的驗證流程我嘗試了好久怎麼用都是失敗,

只能一直上網查範例,用plurk api的人似乎沒有很多,而且感覺比較多是用pyhon寫的比較多

最後找了很多的oauth php的library來使用,但是都失敗,不曉得是不是我不會用的關係,就是

一直失敗,找了好久終於找到了一個方法,用php的擴展Windows下直接在這邊http://downloads.php.net/pierre/依照自己的版

本下載dll檔然後再到php.ini裡面打開他,完成了oauth的部分,步驟都和twitter差不多,之後再

回到library裡面直接填上最後得到的那組 oauth_token和oauth_token_secret 就能夠發文了,

另外他也和twitter一可以有其他的選擇,而且他還有提供測試工具,非常的方便!其他的功能

可以從這邊看 http://www.plurk.com/API  測試工具的部分,申請玩consumer key及consumer

secret 之後在應用程式那邊就會看到了。



雖然最後找到擴展,但是想使用到twitter卻也沒辦法成功,不曉得問題出在哪裡,

接下來要開始測試和資料庫的結合了。








2012年3月18日 星期日

Note2

        上一次提到的問題在網路上有獲得解答了,facebook、twitter、plurk,在授權之後會配發

一個access_token&access_token_secret (Facebook 只有一個access_token),這次Facebook利用SDK面內建的函式很容易就可以取取得access_token,而twitter和plurk要拿到access_token就沒那

麼容易也上網查了很多資料,也問了一些有寫在blog上分享心得的人,感謝願意幫助的人,但

是有的就沒下文了。取得Access_token之後直接照著sdk跑似乎是失敗的,最後終於在google的

幫助下找到了答案,必須要在login的時候多宣告一個scope=>offline_access

<?php
require 'src/facebook.php';

//Create facebook instance.
$facebook = new Facebook(array(
  'appId'  => '377172255645552',
  'secret' => '0901a2d858e2edd546948d5697aefaa1',
  'cookie' => true,
));

$loginUrl = $facebook->getLoginUrl(array(
    'canvas' => 1,
    'fbconnect' => 0,
    'scope' => 'offline_access,publish_stream'
));

$post =  array(
//裡面可以傳入一些變數,可以參考這邊http://developers.facebook.com/docs/reference/api/post/ 
//Facebook的api網頁
//這邊是只有簡單的放了兩個變數
'access_token' =>'利用函式取得的access_token',
'message' => 'This message is posted with access token - !!' 
);
$facebook->api('/me/feed', 'POST', $post);

?>

接著還是這個禮拜的問題 plurk在網路上找範例,真的不是那麼好找,官方提供的api必須是已

經取得了access_token & access_token_secret  才能夠運作,twitter則是因為國外比較多人使用,

範例比較多比較好找,在試看看了。








2012年3月3日 星期六

Note1

經過這幾個禮拜看了好多網站都用不好,到後來才了解現在的社群網站多是使用oauth來做

授權的動作,之前沒有使用過php來登入一個網站,因此在網站上找了些資料,

但是找到的api都失效了,只能依照官方網站上面所提供的api來操作,但是也是初次使用不是

那麼的了解這些東西,大部分都是要和官方網站申請一個APP,接著會產生一組Comsumer Key

跟 Comsumer Secret,接著就能夠利用這組key和secret在網站上寫自己的程式。Twitter的API 下載

https://dev.twitter.com/docs/twitter-libraries之後將config.php內的值修改為網站上申請的APP就可以

了;FaceBook SDK 下載之後再在http://developers.facebook.com/docs/reference/php/facebook-api/

找到範例接著再將檔案內的key和secret修改並執行,但是Facebook在申請app的時候必須使用對

他們來說合法domin,因此我先試了no-ip但是很可惜並不合法,後來換了co.cc才成功;Plurk 到

官網的API下載http://www.plurk.com/API 之後解壓縮將config.php.sample 改為 config.php並填上key

和secret 。


照著上面的api應該就可以成功的在塗鴉牆上發布內容,但是問題出現了如果每次都要使用者登

入的話,必須讓程式知道我是哪個使用者,目前還是沒有找到解決的方式。