顯示具有 問題排除 標籤的文章。 顯示所有文章
顯示具有 問題排除 標籤的文章。 顯示所有文章

2019年4月10日 星期三

【Android AES】SHA1PRING + Crypto

Google提供的範例檔案


好像是Android6以後,AES加解密如果是使用SecureRandom這個物件搭配演算法「SHA1PRING」和Provider「Crypto」來取得RawKey(用來產生SecretKeySpec時需要的導入參數),會發生失敗的情況。

雖然Google提供了一組叫做CryptoProvider的物件在網路上讓人下載(或複製貼上),但在Cipher進行解密(執行dofinal這個函數)時一樣會出錯。

Google這個超級天才就繼續提供了一組物件叫做「InsecureSHA1PRNGKeyDerivator」在網路上,(載點在上面,)來解決這個問題。


這個物件的用法很單純,就是呼叫一組static物件取得Instance然後再導出 RawKey即可。

方法大概是這樣...

byte[] raw = InsecureSHA1PRNGKeyDerivator.deriveInsecureKey(seed, 16);

比較詭異、比較巧妙的是這個「16」,因為大多數使用這個物件的範例都使用「32」,可是解密部分一樣會在Cipher的地方出錯。這似乎是看你使用的Key長短而定,或是你設定的加密位元。

(32是256位元?16是128位元?)

其他部分都可以循著一般標準範例。

2019年2月11日 星期一

【Android】修改螢幕亮度

應該是Android 6.0以後,這類的硬體功能調整光是在Manifest檔中加上「User-Permission」並不夠,還需要有「權限啟動」的通知。

Intent intent1 = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);intent1.setData(Uri.parse("package:" + getPackageName()));intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(intent1);

方法大概如上。這個功能會啟動特定APP的權限管理頁,讓使用者決定是否要自己打開權限。

但在執行這行之前,要詢問系統是否有「執行他們」的能力,--是否有修改Setting的權限。

Settings.System.canWrite

這是個函數,後面要傳入「Activity」作為參數。

如果回傳false,就表示權限未開啟,如果執行程式碼會導致當機。


之後就是很一般的程式碼,直接取得Setting類別後,要求修改特定參數。

android.provider.Settings.System.putInt(
        getContentResolver(),        android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE,        android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);android.provider.Settings.System.putInt(
        getContentResolver(),        android.provider.Settings.System.SCREEN_BRIGHTNESS,        brightNeess);

brightNeess這個參數要自己自訂。(寫死?或是可以讓使用怎選取、輸入想要的數直。)

2018年12月6日 星期四

【Android】如何讓WebView大小自動擴展為內容的大小

WebViewClient的「onPageFinished」被呼叫執行時,就表示網頁已經有一個初步的大小可供計算。但從Java端並無法去取得這個到小,只有網頁本身可以知道自己的大小,所以我們必須要使用JavaScriptInterface去取得這個大小。

在「onPgaeFinished」內執行一段JavaScript:「"javascript:MyApp.resize(document.body.getBoundingClientRect().height)"」,功能大概是說「執行resize這個函數,並將網頁body的高度傳入。」

所以接著要設計一個名稱為「resize」的函數並掛上「@JavascriptInterface」。

函數的內容基本上是重新設定整個WebView的LayoutParams,尤其是寬高。

高度的算法大概是「height * getResources().getDisplayMetrics().density」,「height」大概就是在JavaScript中傳入「resize」函數的數值。因為網頁有自己的高度單位,所以要換算成density才能取得正確大小。


注意!要記得執行addJavascriptInterface這個功能。這是讓網頁內容可以取得加註了「@JavascriptInterface」函數的必要辦法。(記得「javascript」中的「MyApp」和這裡的「MyApp」是連動的,如果要修改或自訂,記得一起完成。)


以下是更完整的程式碼。
private void setupWebView() {
    webView.getSettings().setJavaScriptEnabled(true);
    webView.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            webView.loadUrl("javascript:MyApp.resize(document.body.getBoundingClientRect().height)");
            super.onPageFinished(view, url);
        }
    });
    webView.addJavascriptInterface(this, "MyApp");
}

@JavascriptInterface
public void resize(final float height) {
    MyActivity.this.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            webView.setLayoutParams(new LinearLayout.LayoutParams(getResources().getDisplayMetrics().widthPixels, (int) (height * getResources().getDisplayMetrics().density)));
        }
    });
}

2018年10月29日 星期一

演算法練習 「GenomicRangeQuery」 (快速計算矩陣內單位總和的方式)

題目和解法...

講義...

一連串長度為X的數值矩陣,如何知道單位M和N之間有不為零的數值?(M>N,且絕對不小於零或大於等於X,所以M和N單位絕對都在矩陣內。)


這其實是個變相計算總和的技巧。
如果把矩陣從頭(最小單位)跑一次迴圈,並且每次都把前一個單位的值和自己做加總,例如「X[A] = X[A] + X[A-1]」,則等到迴圈跑完,這個迴圈的每個單位(i)會變成「從0到i單位的總和」,如果要知道每個單位原本的值,只需要把單位(i)減去單位(i-1)就好。
如果要問「i到j之間單位的數值總和(假設j > i)」,也只需要把單位(j)減去單位(i)就好。



所以如果題目要知道ATCG在基因序列中出現的頻率,那就宣告四個和基因序列等長的矩陣,個別對應到ATCG,每次只要出現相對應的序列,就在那個矩陣單位中加一(X[A]=1)。

如果C[i] = N,而C[i + a] = N+2,這就表示在「i」到「i+a」這中間的單位裡,C出現了兩次。這個C[i] - C[i+a]如果稱為F(C, i, 2),則按照題目的要求,F(A, i, j)不為0時答案為1,F(C, j, j)不為零時答案為1......

2018年7月5日 星期四

【Android】Render截圖

為什麼要註明Render截圖?

因為目前Android官方推出的標準截圖方法必須建立在「有辦法取得影片檔案的Description」上。

但影片格式越來越多樣,即使檔名不變,但Description可能無法支援的情況會發生。

所以必須要直接從Render上取得「要撥出的影像畫質內容」。

關鍵在於取得Render內的GL10。(其實不是「Render內」,而是onRenderDraw/onDrawFrame這些函數中,會取得GL傳入的GL10。)

取得後,資料轉換的方法就很固定了。
void screenShot(GL10 gl) {
     int screenshotSize = mCurrentViewportWidth * mCurrentViewportHeight;
        ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
        bb.order(ByteOrder.nativeOrder());
        gl.glReadPixels(0, 0, mCurrentViewportWidth, mCurrentViewportHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb);
        int pixelsBuffer[] = new int[screenshotSize];
        bb.asIntBuffer().get(pixelsBuffer);
        bb = null;
        Bitmap bitmap = Bitmap.createBitmap(mCurrentViewportWidth, mCurrentViewportHeight, Bitmap.Config.RGB_565);
        bitmap.setPixels(pixelsBuffer, screenshotSize-mCurrentViewportWidth, -mCurrentViewportWidth, 0, 0, mCurrentViewportWidth, mCurrentViewportHeight);
        pixelsBuffer = null;

        short sBuffer[] = new short[screenshotSize];
        ShortBuffer sb = ShortBuffer.wrap(sBuffer);
        bitmap.copyPixelsToBuffer(sb);

        //Making created bitmap (from OpenGL points) compatible with Android bitmap
        for (int i = 0; i < screenshotSize; ++i) {                  
            short v = sBuffer[i];
            sBuffer[i] = (short) (((v&0x1f) << 11) | (v&0x7e0) | ((v&0xf800) >> 11));
        }
        sb.rewind();
        bitmap.copyPixelsFromBuffer(sb);
        
        
    }




2018年6月27日 星期三

Eclipse上輸入Picasso (連Maven都不用)

為了使用相較之下比較精簡的MD360Android,所以開始使用Picasso,(不然之前都使用Glide。)

okhttp和okio這兩個專案都有提供jar檔,可以直接下載下來輸入libs中使用。

GitHub內的Picasso專案,扣掉TestUnit Package外,其實就可以簡單拆解成四個項目:Picasso、Picasso-pollexor、Picasso-provider、Squareup-pollexor。





但再仔細觀察,這四個專案其實都沒有res內容,也就是說可以直接整併在同一個專案下。Squareup-pollexor甚至只是個純Java-client的專案。

Picasso專案內本身並不包含「Squareup-pollexor」的程式碼,是在gradle的builder中匯入,所以要使用搜尋的方式找到這個專案才可以。(直接使用Package的名稱,如果使用Pollexor或Thumbor,都有其他相同名稱的專案存在。)



因為都沒有使用到Resource檔的內容,本來應該編譯完就可以直接輸出一份jar做使用了!

(懶人說明)額外注意的是:最新的Picasso的Package名稱是「com.squareup.picasso3」,GitHub上很多使用Picasso的第三方專案都還在使用「com.squareup.picasso」,所以只要修改import名稱即可使用。


最新版本「Picasso3」的特色是:不能直接使用「Picasso類別」的static函數,必須要先從「PicassoProvider類別」的static函數「get」取得;但直接做一樣會出錯,因為PicassoProvider中沒有Context參數,而它是使用Provider去獲取Context參數,所以必須要在專案的AndroidManifest檔中加入PicassoContextProvider的設定值。

因為這篇文章是使用Eclipse,不搭配Gradle或Maven,所以參數檔的寫法要注意...

在PicassoProvider套件專案內可以找到一個AndroidManifest檔,裡面有這個Provider的設定寫法。

<application>
<provider
android:name=".PicassoContentProvider"
android:authorities="${applicationId}.com.squareup.picasso3"
android:exported="false"/>
</application>


但要注意,直接複製貼上會引來編譯器錯誤,必須要把含有「$」的「applicationId」直接刪除,然後「name」標籤後面要加上檔案路徑(修改為「com.squareup.picasso3.PicassoContentProvider」)。

2018年5月24日 星期四

[路徑]\android.jar is neither a directory nor file (type=1).

這是Android SDK更新檔案失敗時經常會做的處置。

仔細看...SDK Manager更新個別Plateform檔案的方式是「把舊的砍掉」「新建一個」「把新的改成跟舊的一樣的名字」。

但如果更新的過程失敗,例如「新建一個」失敗?它並不會把砍掉的Plateform檔案還原,而是就任由它那樣空置在那裏。

這時候IDE就會發現專案找不到相對應的Plateform檔案,但關於「Builder/Plateform」的名單卻沒有更新,使用者就會看到IDE一直在那邊試圖讀取在SDK中已經不存在的Plateform檔案。


退出IDE、重新更新一次SDK,其實就可以輕易的修好這個Bug。

(同樣的理由,有時候運行的很正常的專案有一天會忽然「沒有指定任何Plateform」,就是因為更新的過程中,它刪除了Plateform檔但又一直無法更新成功,所以就先讓IDE更新了Plateform名單,但之後很巧妙神奇地完成了Plateform檔更新,也再次更新了Plateform名單。)

2018年5月10日 星期四

【Android Line Login API】Eclipse上使用Line Login API時碰到Activit not found的解決辦法

呼叫Line的功能會使用到「com.linecorp.linesdk.auth.internal.LineAuthenticationActivity」和「com.linecorp.linesdk.auth.internal.LineAuthenticationCallbackActivity」。

可以在aar檔解壓縮後的Library內找到AndroidManifest.xml檔,並用標準Eclipse的方式匯入。

(Line SDK有提供Maven版。但我一樣沒有用。)


在Library內的AndroidManifest檔下有這兩個設定值,將它們完整複製下來、貼到自己的工作專案下,(光是直接import並不夠,)然後每個「android:exported」都改為true。

接著就可以正常使用了。



        <activity
            android:name="com.linecorp.linesdk.auth.internal.LineAuthenticationActivity"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:exported="false"
            android:launchMode="singleTop"
            android:theme="@style/LineSdk_AuthenticationActivity" />
        <activity
            android:name="com.linecorp.linesdk.auth.internal.LineAuthenticationCallbackActivity"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="lineauth" />
            </intent-filter>
        </activity>

不要搬移這段設定值,程式依然可以正常執行,但是當進行登入時,系統層的logcat訊息會跳出「Activiy」找不到的警訊然後中斷執行,(在APP層的logcat中看不到。)

還在使用Eclipse的人有興趣可以試試看。


會注意到這點,是因為使用FCM時也碰到類似的情況:必須要把Library中的Manifest檔設定內容搬到APP中的Manifest檔中。

感謝Dandar3寫的說明文件讓我有解決這個問題的基礎。(歡迎大家去Github上拜訪他一下。)

2017年12月16日 星期六

【AWS & RDB & EC2】讓已經存在的EC2上的專案存取新建立的RDB instance

這實在是很矛盾的一件事,但RDS DB可以讓外界(非AWS的環境)存取,可是自己內部的EC2要連線卻需要設定層層關卡。

(據說,這是安全需要。其實RDS DB都有對外部連線設下層層保護,並不是單純的只靠帳號密碼和Endpoint而已。反而是內部的雲端伺服器群可能會有安全疑慮,所以反而要層層把關。)



如果沒有特別選擇,其實AWS會自動把使用者建立一組default的VPC。(不知道什麼是VPC的人就比較尷尬,因為我不知道怎麼精準正確的解釋。就先假設它是種為了使用者設計的「沙箱式」的防火牆,在這牆內的任何AWS雲端虛擬主機都可以視為在同一個子網域中。──解釋的很爛。)

官方標準Guide文件「Create VPL Connect RDS DB」並沒有提到這點,就好像它們也不會說「虛擬機建好以後不能修改VPC」。──VPC的內容可以隨意修改,Instance的各項設定也可以隨意修改,唯獨一旦指定VPC,除非Instance整個刪除否則這項設定不會再更動。


所以某些情況下,建立了一組EC2虛擬主機後也在上面安裝了資料庫的人,可能會想要改用AWS RDS DB服務,這時可能就會碰到不知從何下手的困擾。

幸運的是:建立EC2時即使沒有新建VPC,系統也會幫忙設定一組VPC,而且這組VPC內的設定一應俱全。有Subnet、也有SecurityGroup。而且在新建RDS DB Instance時也可以選用這組PVC。

所以如果想要讓EC2可以存取使用RDS DB,只要找到這組VPC即可。

(這組VPC的名稱也可以修改,修改後就可以快速找到相對的Subnet和SecurityGroup,然後進行修改。)

(修改的原則跟新建時的原則並沒有太多不同。所以可以參考剩下的官方文件、將剩餘步驟改成「修改現有EC2 Instance」和「新建RDS DB並使用現有VPC」即可。)

2017年12月11日 星期一

【AWS & RDB】設定中文語系

AWS上有「建立資料庫虛擬機」的服務。(就是一個只有資料庫,除此以外啥都沒有的虛擬機。

(簡單使用過了以後的想法是:)XAMPP這樣的軟體或組站法很興盛,所以大家可能會習慣(以為)把資料庫和服務供應器架在一起是件好事,但其實服務不一定會只有一套,例如「後台」和「前台」可以分開成兩套供應器,而且只要資料庫還活著、服務供應器隨時可以整個打掉重新架構。


比較值得一提的是:AWS上的資料庫預設都不支援中文,因為語系設為latin,所以需要調整。

調整的方式是設定RDB Instance所接受的ParameterGroup。

如果沒有自己進行過「新增ParameterGroup」,那RDB Instance會自動幫使用者設為「預設/default」,這組Group內的參數都不能修改。──所以要自己新增一組後,再到Instance下去修改ParamterGroup的「指向」。


怎麼編寫自己的ParameterGroup?建議參考一下default的內容。到(左邊的面板中)ParamterGroup中把deault group打開,(這個default的名稱並不是絕對的,可能大家的名字都不一樣,所以就一律稱為default就好。)可以看到所有的參數被條列呈現。

用「char」做關鍵字,就可以看到有那些跟語系有關的選項。將參數名稱記錄下來、然後在自己新增的group中用手動輸入的方式輸入,就可以有這個屬性。


但是修改RDB Instance的ParamterGroup設定,需要決定「要即刻生效」還是「等排程」,即使選了「即刻生效」,似乎還是要用「Reboot」以後才會讓設定生效,這是比較奇怪的地方。


=============================

AWS的RDB在使用上跟一般SQL幾乎沒有什麼不同。

要指定連線的帳號密碼、用的Driver也是標準SQL Driver。

只是連線用DB Name會在設定Instance時決定,連線用網址(無IP)會在設定完後的Instance詳細資料內用「Endpoint」的名稱顯示。(挺奇妙的命名邏輯。)

2017年11月29日 星期三

【XAMPP】修改正式網站的首頁,或新增服務 (Windows環境)

1.怎麼將Tomcat下的Java專案新增到Apache中讓外部的網址可以找到它。
2.怎麼修改XAMPP的預設首頁服務。



XAMPP是一套軟體,可以幫助下載的人快速安裝好Apache+MySQL+Tomcat。同時MySQL還附帶phpMyAdmin這套視覺化的管理工具。

問題是XAMPP是預設給PHP設計族群使用的工具,裏頭的Tomcat也是「預設」執行PHP,這並不是什麼「問題」,但這導致在網路上關於它的資訊或討論就很少是針對Java族群。



以單純的在Apache上新增一個PHP Service來說,只要把整個PHP專案資料夾複製到XAMPP下的「htdocs」資料夾即可。(注意!為什麼Apache會自動去htdocs下找網站首頁?這也是個「學問」。)

雖然Java專案一樣只要把專案複製到Tomcat的webapps下,重新啟動的時候Tomcat就會自動執行這個專案,但用瀏覽器時只有在「http://localhost/」下才可以找到這個專案,用IP或外部網址其實找不到。

因為在Apache和Tomcat之間是用一種叫做AJP的方式溝通......完全不知道這是什麼,只知道AJP有兩大系列(是不是只有這兩種?我不肯定!):mod_jk和mod_proxy_ajp。

一個標準的Apache其實並不包含這些模組,必須要自己去下載模組後安裝(其實只是把檔案複製貼上)到Apache中,並且寫「一卡車」的AJP設定檔,並且在設定檔中寫明了「Apache要怎麼去Tomcat中找到專案」。──XAMPP的好處就是幫使用者省去了這個步驟。(否則安裝Apache並不難。)

接著我們只需要搞懂XAMPP使用的是哪種版本的AJP協定。最標準的作法是到Apache下的module資料夾去找,這兩個模組其實就是檔案名稱,有模組的檔案名稱就表示這個Apache使用了哪一個模組。

(講精準一點來說,我這是預設安裝並架設Apache+Tomcat環境的老兄不會很多事的下載兩套版本的檔案,如果他真的這樣做了,那就只能從設定檔去看他幫Apache選擇使用了哪套,如果他又很多事的兩套都寫了AJP設定檔,那就只能去找看看Apache內部的設定檔「httpd.conf」中指示了會載入哪一套協定。)

XAMPP使用的是mod_proxy_ajp。(如果要尋找額外的資源,可以用這個方式更精準地找到資訊。)



「Localhost」在Server上(疑似)為「127.0.0.1」這個IP的默認。所以要將Tomcat中的Java專案新增到Apache中,必須要用「http://127.0.0.1/[專案名稱]」這樣的方式寫入設定檔。

(XAMPP中)設定檔名稱為「httpd_ajp.conf」。

設定檔的寫法是...

「ProxyPass "/[專案名稱]" "http://127.0.0.1/[專案名稱]"」和「ProxyPassReverse "/[專案名稱]" "http://127.0.0.1/[專案名稱]"」。──1.新增完建議重開Apache。2.「ProxyPassReverse」似乎可以不用加。


完成以上步驟只是讓Apache可以搜尋到Tomcat中的Java專案。

接著到htdoc中找到「index.php」,把裡面的「header('Location: '.$uri.'/dashboard/');」這段程式碼的「dashboard」改成專案名稱,接著應該就可以順利在首頁找到預期看到的專案了。

2017年9月20日 星期三

中國大陸的長城擋連線,無法分享檔案

如標題。

大陸內的硬碟空間(微信、百度、QQ)註冊非常繁瑣,都要有個手機門號才能使用,而國外國際間慣用的網路空間幾個有名的大站都被一律封鎖。

如果要知道國外空間能否讓大陸內部取得,可以使用測試網站看看能否連線.......


這次使用的是WEBKAKA....


 這是它的首頁...選擇「國內網站測速」。


選好了往下滑,可以看到這個頁面,右邊的輸入欄就是用來要測速/可否連線的網址輸入欄。




可以看到OpenDrive網站可以連通。