Friday, July 21, 2017

Little planets effect (小行星特效)



I got a task to implement this effect recently.
Before it's assigned to me, there was a fragment shader in the codebase to handle this effect.
But the view angle can not be rotated.
So I try to "google" whether there is any information about it.
Then I found this page .
It's a way to project a sphere to a plane.
It's called "stereographic projection";

Φ = asin( cos(c) sin(Φ0) + (y sin(c) cos(Φ0) / )
λ = λ0 + atan( x sin(c) / (r cos(Φ0) cos(c) - y sin(Φ0) sin(c) )
I can use the above equation to calculate the position correspond to the x,y coordinate on the plane. 
After I adjust the fragment shader by the equation, the user can watch this planet at any angle.
It's quite interesting to try the OpenGL shader, I can generate such amazing results by a few lines of code.

By the way, if you would like to try such kind of effect by your self, you can download  Insta360Player.
If I didn't find a way to implement the little planets effect, I will try to decompile it's apk.


Saturday, July 15, 2017

Android OpenGL Texture memory occupied

I try to solve an interesting memory issue recently.

There is a viewer page in a project I owned recently.
The whole app will be closed without showing the "force close dialog" if we keep entering and leaving that page.
It seems like a memory leak , so I try to use LeakCanary to check it but found nothing related.

Then I try to use the  Memory Monitor  in Android Studio to monitor the memory usage.
But all the memory is released after the GC.

So I can only record the logs during that period and check it line by line.
Then I notice that many process is killed by Activity Manager during that period.
Even a process with OomAdj 0 (contain a foreground activity) is killed too.
It's quite abnormal that Activity Manager will kill so many process when I can't found any app spend lots of memory.
It pops into my mind there is a lesson learned I got in HTC .
In the early version of Android , the memory of a Bitmap can be allocated in the native layer.
Is it the reason it's not watched by the Memory Monitor?

So I try to survey whether there is any command I can use to check the memory usage in native layer.
Then I found the command below.


adb shell dumpsys meminfo <package_name|pid> [-d]

After I execute it, I LOL.
EGL mtrack is fucking high!!



It seems like the memory related to the OpenGL in this page is not released correctly.
After I found the hint, it's much easier to solve this issue.

Monday, May 15, 2017

Practice Line Bot

之前就看過Julian大大分享的 Line Bot 心得
所以大概知道Line Messaging API 運作的方式
不過一直都沒想到比較有意思的題目, 所以就沒寫來玩玩看

最近突然想起, 有時候忘了看女兒的聯絡簿時, 都不知道她們最近教了些什麼東西
於是就決定來寫個聯絡簿的通知小幫手

首先由於我比較熟悉的後端框架是node.js , 跟 J大用的 GO 不同
所以還是另外參考了node上的Line bot 教學文章

在 Line Business Center 申請好帳號之後
需要設定Webhook的網址
也就是 Line 會把一些 event 透過 http 發到該網址

首先npm install linebot --save 之後 ,就能安裝node下的linebot 套件
寫了最基本的程式碼後 , 就能監聽收到訊息時的event
(還得上傳上 Heroku 或類似的服務)

let app = express()
const server = require('http').Server(app)
let bot = LINEBot.create({
  channelID,
  channelSecret,
  channelToken
}, server)

bot.on('message', function(event) {
  console.log(event); //把收到訊息的 event 印出來看看
});

app.use(bot.webhook('/webhook'))

能夠知道使用者發了怎樣的訊息 , 就能利用字串比對的方法
來應答各種不同的回覆訊息

但是我準備嘗試的聯絡簿通知幫手 , 並不需要針對使用者的訊息做回應
而是定期的去爬學校的電子聯絡簿網頁 , 然後發現有新的內容時, 就發給所有使用者

所以在event的部分, 我關心的只有哪個 user 或哪個group 加了我的bot
或移除了bot , 我只要在DB維護這個 userId 跟 groupId的清單
每當有新的聯絡簿內容時 , 就發給他們即可

爬蟲的部分, 我就參考上面連結中使用的 js-crawler 跟 cheerio 兩個套件
去處理學校的聯絡簿網址 , 然後再分別拿到聯絡簿內容與當天的日期
如果發現當天沒有聯絡簿內容(可能老師還沒寫或當天是假日) ,就直接結束
如果有看到內容就將該日期與內容與 DB 內最新的內容做比對
如果日期不同, 就刷新 DB的內容, 並將內容發給所有訂閱的userId / groupId
如果日期相同, 就代表該內容已經發出去過了, 可以略過

雖然兩三年前就加減學過node.js , 但一直也沒有一個題目來認真寫
這次這個題目不僅嘗試了 Line的 Messaging API
另外也第一次在 node.js上使用 mongo db 跟爬蟲
而由於這一些非同步的指令在javascript 上都會使用callback來回傳結果
所以初版寫完之後, 馬上就遇上又臭又長的 callback hell

還好這半年有在Android 上使用 RxJava的經驗
在Javascript上學起 Promise 就較為容易上手
於就再花了些時間把code用Promise 重構 (聽說 Async / Await 更潮, 不過就下次吧)