2017年3月26日 星期日

Android在Thread中改變外部類別的View元件


  • 準備一個handler來接收呼叫,然後在handler中改變View元件:
Handler mHandler = new Handler() {
    @Override    public void handleMessage(Message msg) {
        if(msg.what == 1)
        {
            status.setText(response);
        }
        super.handleMessage(msg);
    }
};

  • Thread中要改變View元件處改為呼叫handler:

Message msg = mHandler.obtainMessage();
msg.what = 1;
msg.sendToTarget();

Android對URL的Get與Post


  • 首先,我們要注意的是:Android使用網路資源必須使用Thread!
     示範的Thread的寫法,是使用匿名內部類別+匿名物件的方式:

    (new Thread(){
        public void run() {
            //使用網路資源的程式寫在這裡!
        }
    }).start();
    
   因為使用了匿名類別,所以如果有建立變數,他的生存空間只在run裡面哦,但是run裡面可以存取外部類別的屬性!
  • POST的寫法:
        
         try {
            // Create a URL for the desired page        
            String response = "";
            URL url = new URL([要POST的網址]);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(3000);
            conn.setConnectTimeout(5000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);
            HashMap postDataParams = new HashMap();
            postDataParams.put("[參數名稱一]",[參數字串一]);
            postDataParams.put("[參數名稱二]",[]);
            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
            new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));
            writer.flush();
            writer.close();
            os.close();
            int responseCode=conn.getResponseCode();
            if (responseCode == HttpsURLConnection.HTTP_OK) {
                 String line;
                 BufferedReader br=new BufferedReader(new InputStreamReader(conn.getInputStream()));
                 while ((line=br.readLine()) != null) {
                        response+=line;
                 }
             }
             else {
                 response="";
    
             }
         }
         catch (Exception e) {
                Log.d("Debug", e.toString());
         }
  • GET的寫法:

  • 跟POST一樣,只差在: 1.網址可以直接帶GET字串(?[參數名稱一]=[參數字串一]&[參數名稱二]=[參數字串二]) 2.conn.setRequestMethod("POST");改成conn.setRequestMethod("GET");

2016年5月14日 星期六

Android自訂返回鍵並且實作連續按兩下返回鍵退出程式

在MainActivity中增加以下程式:

 private static Boolean isExit = false;
private static Boolean hasTask = false;
Timer tExit;
TimerTask task;

@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event)
{
    if (keyCode == KeyEvent.KEYCODE_BACK)
    {
        mAppWebView.loadUrl(mMenuURL); //自訂返回鍵按下後做的事情
        if(isExit==false)
        {
            isExit=true;
            Toast.makeText(this, "再按一次後退鍵退出應用程式",Toast.LENGTH_SHORT).show();
            if(!hasTask)
            {
                hasTask = true;
                tExit = new Timer();
                task = new TimerTask()
                {
                    @Override                    
                    public void run()
                    {
                        isExit = false;
                        hasTask = false;
                    }
                };
                tExit.schedule(task, 1000);
            }
        }
        else       
        {
            finish();
            System.exit(0);
        }
        return false;
    }
    return super.onKeyDown(keyCode, event);
}

Android webView 中的網址連結轉處理方式(呼叫開啟Assets中的檔案,開啟外部網址)

建立一個MyWebViewClient的Class file
在裡面的shouldOverrideUrlLoading方法中可以攔截到<a href="XXXXXX">中href指向的位址=>放在url!
檔案內容如下:

import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


/** * Created by ray on 2016/5/14. */
public class MyWebViewClient extends WebViewClient {

    private Context context;

    public MyWebViewClient(Context context) {
        this.context = context;
    }

    @Override    public boolean shouldOverrideUrlLoading(WebView view, String url)
    {
        if(url.contains(".pdf") || url.contains(".doc"))
        {
            //處理取得純檔名(過濾掉路徑)            
            String[] fa = url.split("/");
            String filename = fa[fa.length-1];
            
            //將檔案從assets複製到SD card或手機內部儲存空間
            InputStream in = null;
            OutputStream out = null;
            AssetManager assetManager = this.context.getAssets();

            try {
                in = assetManager.open("app-land/file/"+filename);
                //注意路徑的前面不要有/
                File outFile = new File(this.context.getExternalFilesDir(null), filename);
                out = new FileOutputStream(outFile);
                copyFile(in, out);
            } catch(IOException e) {
                Log.e("tag", "Failed to copy asset file: " + filename, e);
            }
            finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        // NOOP                    }
                }
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                        // NOOP                    }
                }
            }
            //呼叫開啟詢問怎麼打開這個文件
            Intent intent = new Intent( Intent.ACTION_VIEW );

            File ff = new File(this.context.getExternalFilesDir(null)+"/"+filename);
            intent.setDataAndType(Uri.fromFile(ff), "application/*" );
            this.context.startActivity(intent);

            return true;
        }
        else if(url.contains("http"))
        {
            //開啟外部網址的處理
            Uri uriUrl = Uri.parse(url);
            Intent launchBrowser = new Intent(Intent.ACTION_VIEW, uriUrl);
            this.context.startActivity(launchBrowser);

            return true;
        }
        return super.shouldOverrideUrlLoading(view, url);
    }

    private void copyFile(InputStream in, OutputStream out) throws IOException
    {
        byte[] buffer = new byte[1024];
        int read;
        while((read = in.read(buffer)) != -1)
        {
            out.write(buffer, 0, read);
        }
    }
}
----------------------------------------------------
在MainActivity.java中的WebView部分程式加入以下的設定:
mAppWebView = (WebView) findViewById(R.id.webView);
mAppWebView.getSettings().setJavaScriptEnabled(true);
mAppWebView.getSettings().setSaveFormData(true);
mAppWebView.getSettings().setDatabaseEnabled(true);
mAppWebView.getSettings().setDomStorageEnabled(true);
mAppWebView.getSettings().setSupportZoom(true);
mAppWebView.getSettings().setAllowFileAccess(true);
mAppWebView.getSettings().setAllowContentAccess(true);
mAppWebView.setWebViewClient(new MyWebViewClient(this));//這一行!
mAppWebView.loadUrl(mAppURL);


---------------------------------------------------


最後是要在AndroidManifest.xml增加permission:



</application> <---放在這一行的後面哦!
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2016年4月8日 星期五

對mysql的欄位進行split的方法

先宣告原文出處:http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/
我在網路上找到一篇,先建立一個function,然後就可以使用該function達到目的了!
再搭配CONVERT使用就可以把分離出來的字串轉成數字避免排序不如預期的情況了~
例如:CONVERT(SPLIT_STR(week,'-',1),UNSIGNED INTEGER)
以下是function的寫法以及用法
Function
CREATE FUNCTION SPLIT_STR(
  x VARCHAR(255),
  delim VARCHAR(12),
  pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, '');
Usage
SELECT SPLIT_STR(string, delimiter, position)
Example
SELECT SPLIT_STR('a|bb|ccc|dd', '|', 3) as third;

+-------+
| third |
+-------+
| ccc   |
+-------+
最後順帶一提,在mysql中建立的function會跑到哪邊呢?
會在database: mysql     table: proc裡面!


2015年11月15日 星期日

使用jQuery支援所有瀏覽器播放音效

首先要準備音效檔,因為要支援幾乎所有的瀏覽器,所以我們要準備三種格式的音效檔:
music.ogg
music.mp3
music.wav

然後將支援三種音效格式的audio元件注入:
$(function()
{
    $('<audio id="myAudio"><source src="music.ogg" type="audio/ogg"><source src="music.mp3" type="audio/mpeg"><source src="music.wav" type="audio/wav"></audio>').appendTo('body');
});

在要播放的時候執行以下呼叫:
$('#myAudio')[0].play();  //myAudio為注入audio元件時設定的id

使用jQuery遍歷指定Class的DOM

如果我們有一堆表格的內容需要依照規則去處理,我們可以將這些<td>的class設為相同的,然後使用以下當方式遍歷所有的<td>,然後針對每個被讀到的<td>來進行處理,非常好用呢!

$('.classname').filter(
    function()
    {
 //使用 $(this) 可以存取到可以存取到當下讀到的jQuery DOM !
   });


2015年8月17日 星期一

各種社群分享按鈕的製作

<!--Facebook分享按鈕(純HTML語法)-->
<a target="_blank" href="http://www.facebook.com/share.php?u=<要分享的網址>">
<img title="分享到臉書!" src="https://upload.wikimedia.org/wikipedia/commons/1/13/Facebook_like_thumb.png" border="0" width="20" /></a>

<!--Google+分享按鈕(純HTML語法)-->
<a target="_blank" href="https://plus.google.com/share?url=<要分享的網址>">
<img title="分享到Google+!" src="https://www.gstatic.com/images/icons/gplus-32.png" border="0" width="20" /></a>

<!--Twitter分享按鈕(純HTML語法)-->
<a target="_blank" href="http://twitter.com/home/?status=<要分享的標題> <要分享的網址>">
<img title="分享到維特!" src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Twitter_Logo_Mini.svg/2000px-Twitter_Logo_Mini.svg.png" border="0" width="20" /></a>

<!--Plurk分享按鈕(純HTML語法)-->
<a target="_blank" href="http://plurk.com/?qualifier=shares&status=[分享] <要分享的網址> (<要分享的標題>)">
<img title="分享到噗浪!" src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3d/Plurk.svg/1024px-Plurk.svg.png" border="0" width="20" /></a>

<!--微博分享按鈕(純HTML語法)-->
<a target="_blank" href="http://v.t.sina.com.cn/share/share.php?title=<要分享的標題>&url=<要分享的網址>">
<img title="分享到微博!" src="http://www.i-marketing.com.tw/fbliker/wp-content/uploads/2015/07/weibo.png" border="0" width="20" /></a>

2015年7月21日 星期二

php壓縮檔案

$zip = new ZipArchive();
if($zip->open([存放壓縮檔的完整徑名],ZIPARCHIVE::CREATE) !== true)
{
return false;
}
$zip->addFile([要壓縮的檔案的完整徑名],[在壓縮檔中的檔名]);
header("location:".[存放壓縮檔的完整徑名]);//直接輸出壓縮檔供下載

PHP匯出CSV的方式

導向的頁面中用下面的方式就會自動輸出下載

header("Content-type: application/vnd.ms-excel");
header("Content-Disposition: filename=export1.csv;");
//輸出CSV的內容
die();//如果程式後面仍有輸出可以使用




2015年6月21日 星期日

R語言抓取股票價格並計算相關性

這幾天玩R語言,然後我做了以下的測試:
(1)2014年宏達電(t2498)與大立光(t3008)的股價關係
(2)2014年蘋果(taapl)與大立光(t3008)的股價關係
數據方面:
AAPL我是抓google提供的股價,所以已經有還原分割前的價格
大立光股價除以20以免價格與宏達電或蘋果相差太多
測試的結果如附圖:




結論:果然大立光與蘋果的股價高度正相關ㄚ~~

相關程式碼如下:

#!/usr/bin/Rscript
Sys.setenv("HADOOP_PREFIX"="/usr/local/hadoop")
Sys.setenv("HADOOP_CMD"="/usr/local/hadoop/bin/hadoop")
Sys.setenv("HADOOP_STREAMING"="/usr/local/hadoop/contrib/streaming/hadoop-streaming-1.1.2.jar")

library(quantmod)
library(rhdfs)

hdfs.init()
library(rmr2)

makeReport = function(input)
{
  report=as.data.frame(input, stringsAsFactors=F)
  colnames(report)=c('Month','Max Price')
  return(report)
}

getMaxDirect = function(symbol,year,from="google")
{
  stock = getSymbols(symbol,src=from,auto.assign=FALSE)
  monthes=1:12
  data = c()
  for(m in monthes)
  {
    data = c(data,max(stock[paste(year,"-",m,sep=""),4]))
  }
  result=keyval(monthes,data)
  return(result)
}

getMaxReduce = function(symbol,year,from="google")
{
  stock = getSymbols(symbol,src=from,auto.assign=FALSE)
  data=stock[year,4,1]
  monthes=1:12
  date=numeric(length(index(data)))
  for(m in monthes)
  {
    date[index(data)>=as.Date(paste(year,"-",m,"-1",sep=""))]=m
  }
  indata=to.dfs(keyval(date,as.double(data)))
  out=mapreduce(input=indata,reduce=function(k,v) keyval(k,max(v)))
  result=from.dfs(out)
  return(result)
}

getMaxMapReduce = function(symbol,year,from="google")
{
  stock = getSymbols(symbol,src=from,auto.assign=FALSE)
  data=stock[year,4,1]
  indata=to.dfs(keyval(as.double(index(data)),as.double(data)))
  mymap=function(k,v){
    monthes=1:12
    date=numeric(length(k))
    for(m in monthes)
    {
      date[k>=as.Date(paste(year,"-",m,"-1",sep=""))]=m
    }
    keyval(date,v)
  }
  out=mapreduce(input=indata,map=mymap,reduce=function(k,v)keyval(k,max(v)))
  result=from.dfs(out)
  return(result)
}

result=getMaxDirect("AAPL","2014","yahoo")
aapl2014 = makeReport(result)
aapl2013 = makeReport(getMaxReduce("AAPL","2013","yahoo"))
aapl2012 = makeReport(getMaxMapReduce("AAPL","2012","yahoo"))
aapl2012
aapl2013
aapl2014

t3008=getMaxDirect("3008.tw","2014","yahoo")
t2498=getMaxDirect("2498.tw","2014","yahoo")
x=c(t3008$key,t2498$key)
y=c(t3008$val/10,t2498$val)
plot(x,y)
abline(lm(y~x))
cor(x,y)

2015年6月14日 星期日

一個可以方便驗證json的網站

當我們產生出來的json很龐大時,錯誤常常變得不容易發現,這一個網站可以用來驗證我們產生的json是否有問題,以及問題發生大約的位置。
http://www.freeformatter.com/json-validator.html
還真的蠻好用的~

2015年5月27日 星期三

重新溫習Java Applet重點

1.使用NeatBeans打包Applet:
   建立專案時選擇Java Class Library
   然後在該專案中新增一個JApplet Form即可。

2.介面編輯:
   可以先在JApplet Design介面下按右鍵選擇Layout來調整介面。
   Build之前再將Layout選擇回Free Desidn並將Libraries中的Layout相關jar檔remove掉。

3.Html編輯範例:
   <applet width='350' height='30' code="AppletClass.class" archive="AppletClass.jar">
   抱歉,你的瀏覽器不支援Applet標籤!
   </applet>

4.有存取本機相關設備時需要簽章:*
keytool -genkey -validity 3650 -keystore pKeyStore -alias keyName
jarsigner -keystore pKeyStore AppletClass.jar keyName

5.提供Javascript呼叫的函式的寫法:
    public String getSomething()
    {
        String Something;
        //若getSomethingReal()內無牽扯權限的問題可以使用以下寫法
        Something = getSomethingReal();
        return Something;
        //若getSomethingReal()內有牽扯權限的問題必須使用以下寫法*
        AccessController.doPrivileged(new PrivilegedAction()
        {
            public Object run()
            {
                Something = getSomethingReal();
                return null;
            }
        });
        return Something;
    }

6.Client端相關權限設定(不論使用何種瀏覽器都必須先設定好):
   首先依照指示下載安裝Java。安裝完後如下面方式設定。
   Windows的設定參考圖:



   OSX(MAC)的設定參考圖:





7.Chrome對於Java applet即將於45版後徹底不支援,而目前42版為暫時支援,使用方式請參考以下Google的官方說明網址來設定:

2015年3月3日 星期二

Android Phonegap App中Native與Javascript溝通的範例

一、首先建立一個類別:

public class MyJavaScript
{
    private WebView mAppView;
    private DroidGap mGap;
    
    public MyJavaScript (DroidGap gap, WebView view)
    {
        mAppView = view;
        mGap = gap;
    }
    
    @JavascriptInterface //文件說4.2之後須增加這一行,但是實際測試不加亦沒問題。
    public String test(String name)
    {
        return "Hello, " + name;

    }
}

二、讓WebView增加MyJavaScript:

請注意下面的程式必須在super.loadUrl("file:///android_asset/www/index.htm");之後,因為appView在這個之後才存在實例,否則appView為null就會導致下面的程式發生例外。

try
{
        appView.addJavascriptInterface(
                       new MyJavaScript(this, this.appView),"MyAndroidFunctions");
}
catch(Exception e)
{
        Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
}

三、在javascript中測試:

alert(MyAndroidFunctions.test("World!"));

如何使用AD自動派送更新

一、建立分享資料夾:

1. 建立一個分享資料夾,並把權限設定為所有Domain users可以存取。

2. 將要派送更新的檔案放在裡面。

3. 撰寫派送批次檔,例如:

    copy /y "\\10.1.1.1\sw\mySoftware.exe" "c:\Software"
 
上述指令的簡略說明如下:
    \\10.1.1.1\sw:分享資料夾的網路位置。
    mySoftware.exe:將要派送更新的檔案。
    c:\Software:使用者端要被更新的檔案的位置。

4. 將這個檔案存成副檔名為bat的檔案,例如:autoexec.bat。


二、使用AutoIT來包裝RUNAS行為:

1. 下載AutoIT完整版

2. 依照安裝檔的指示安裝下載好的autoit-v3-setup.exe。

3. 使用文字編輯器編寫Script:
 
   RunAs("帳號", "Domain", "密碼", 1, "執行的批次檔")

檔案中只需要上述一行內容,其中帳號密碼須為可以在使用者端電腦上複製檔案的權限,Domain為這個帳號所屬的Domain,執行的批次檔須包含所在位置,且所在位置最好使用網路位址,也就是在第一項建立的分享資料夾的位置。

以下為一個範例:

   RunAs("administrator", "test.com", "pa55w0rd", 1, "\\10.1.1.1\sw\autoexec.bat")

4. 將這個檔案存成副檔名為au3的檔案,例如:update.au3。

5. 在存好的檔案上按右鍵,選擇Compile Script,便會產生一個執行檔,如下圖:

6. 最後將產生的執行檔放到第一項建立的分享資料夾的位置。


三、在AD上面建立使用者的登入原則:

1. 打開伺服器管理員,參考下圖來建立GPO並連結到我們要做用到的網域:


2. 替這個GPO取一個名稱:


3. 在我們剛才建立的GPO上面按下滑鼠右鍵並選擇編輯:


4. 在群組原則管理編輯器的視窗中,參考下圖設定登入的指令碼:


5. 按下新增按鈕:


6. 可以使用瀏覽或是直接打入指令:


7. 我們使用瀏覽選擇在第二項建立的執行檔,注意須使用網路位置:



8. 按下確定應該會是如下畫面,確定你新增的指令碼有在列表中並且正確:


9. 打開命令提示視窗並輸入:gpupdate /force 讓我們剛剛設定的原則立即生效。



四、到這邊應該全部大功告成,使用者登入Domain就應該會執行我們做的設定來更新檔案,如果沒有,請仔細檢查你的「權限設定」。

2014年7月10日 星期四

PHP不透過curl來達到使用POST讀取網頁或CGI

今天在網路上找尋PHP不透過curl來達到使用POST讀取網頁或CGI的方式:
找到以下資訊確實可用:
(原文出處:http://wezfurlong.org/blog/2006/nov/http-post-from-php-without-curl/)
函式宣告:
function do_post_request($url, $data, $optional_headers = null)
{
  $params = array('http' => array(
              'method' => 'POST',
              'content' => $data
            ));
  if ($optional_headers !== null) {
    $params['http']['header'] = $optional_headers;
  }
  $ctx = stream_context_create($params);
  $fp = @fopen($url, 'rb', false, $ctx);
  if (!$fp) {
    throw new Exception("Problem with $url, $php_errormsg");
  }
  $response = @stream_get_contents($fp);
  if ($response === false) {
    throw new Exception("Problem reading data from $url, $php_errormsg");
  }
  return $response;
}
使用方式:
echo do_post_request("http://192.168.172.203/cgi-bin/ed3.cgi","page_charset=big5&userid=admin&userpwd=123456&pagename=26&mainmenu=69&page=0");

2014年6月2日 星期一

form一次選擇多個檔案+php上傳範例

<?
for($i = 0 ; $i < count($_FILES["files"]["name"]) ; $i++) { echo $_FILES["files"]["name"][$i]."</br>"; } ?> <form action='' method='post' enctype='multipart/form-data'> <input name="files[]" type="file" multiple="multiple"/> <input type='submit' value='test'> </form>

2014年3月21日 星期五

PHP下載檔案的正確寫法

<?
$file = $_GET["file"];
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".basename($file));
header("Content-Transfer-Encoding: binary");
$fd = fopen($file, "rb");  //大檔案下載的解決方法~readfile($file)會出問題~
if($fd)
{
    ob_end_clean();
    fpassthru($fd);
}
fclose($fd);
?>

將以上程式儲存成download.php
然後要下載的聯結就以如下方式呼叫:
download.php?file=XXXX
XXXX必須為檔案的完整徑名~~

2013年12月5日 星期四

Node.js建立web service時如何動態指定port

如果我們的web service有可能要占用不同的port而又不希望每次都要改動程式,
我們可以透過外部環境變數來動態改變要占用的port!
如果要可以動態指定,不指定時又有一個預設的port呢?
下面就是這樣的範例(重點在最後一行):

var http = require('http');
http.createServer(function(req,res)
{
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<h1>Node.js</h1>');
res.end('<p>Hello world</p>');
}).listen(process.env.PORT || 80);

所以當你希望他佔住8080 port時:
PORT=8080 node myweb.js
當你希望它使用預設的80 port時(不是管理員身份請記得sudo):
node myweb.js

Node.js建立web service時如何聽80 port?

以下是一個小小的Node.js web service範例:

var http = require('http');
http.createServer(function(req,res)
{
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<h1>Node.js</h1>');
res.end('<p>Hello world</p>');
}).listen(80);

如果我們將他存檔成myweb.js然後執行時,會發生錯誤,但是如果我們將最後一行的
listen(80) 改成 listen(8080) 那就可以正確執行無誤了!

當然以我們的水準絕對不用考慮到是不是犯了80已經被其他web service佔住的錯!

其實只要實驗過就知道,並不是只有80 port 不行,聰明的你看到這邊是不是已經猜到只要是小於1024的port都不行呢?Exactly!只要是小於1024的系統保留port都會出問題~所以這根本就不是Node.js的問題,是我們應該要以系統管理員的身份來執行它:

sudo node myweb.js