發表文章

PendingIntent 速記

什麼是PendingIntent,字面上來看就是 即將發生的intent。 我們知道如果要開始一個Intent,可以如下 Intent x1 = new Intent( this, xxx.class); startActivity(x1); 通常我們是要開啟一個新的activity會用到Intent。我們更應該把 Intent理解為Activity間的一個訊息的傳遞。也就是由Intent這個信使,帶著訊息,告知Activity要啟動了。這樣理解,我們可以推論,Intent可以帶著訊息通知其它class,讓他們啟動。 如 Service Intent x1 = new Intent(this, xxxService.class); startService(x1); 但有時候,我們有一個Intent,我們不想用 startActivity, 或是 startService去啟動,而是希望它等待至某種要求出現才啟動。這就需要用到 PendingIntent。 所以簡單的說,PendingIntent就是把一個已知的 Intent 包起來。然後pending(即將發生)。 我們看一下PendingIntent有幾個靜態方法 包了一個Activity的Intent public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags) 包了一個Broadcast的Intent public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags) 包了一個Service的Intent public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags) 包了多個Activity的Intent public static PendingIntent getActivities(Context context, int requestCode,

Android 自動產生 VIEW ID

動態產生 Layout 時一定會遇到 ID配置的問題。 在API > 17後有提供一個  View.generateViewId(),只要在新增的LAYOUT物件設定即可 Button btn = new Button(this); btn.setId(View.generateViewId()); 如果需要API<17要如何是好?我們深入View.generateViewId()看看。 private static final AtomicInteger sNextGeneratedId = new AtomicInteger( 1 ); public static int generateViewId () { for (;;) { final int result = sNextGeneratedId.get(); // aapt-generated IDs have the high byte nonzero; clamp to the range under that. int newValue = result + 1 ; if (newValue > 0x00FFFFFF ) newValue = 1 ; // Roll over to 1, not 0. if (sNextGeneratedId.compareAndSet(result, newValue)) { return result; } } } 看樣子,是用AtomicInteger來增加ID。利用compareAndSet(CAS)來查newValue是否可以置入result的記憶體位址中。另外我們也看到,newValue最高到0x00FFFFFF,0x00FFFFFF以上就會從1再開始。也代表0x00FFFFFF以上是保留給系統工具使用。 所以,g

Android AudioTrack AudioRecord II

上一篇寫一半,我們把他完善了,針對AudioRecord的部份 new Thread(new Runnable() {   @Override   public void run() {     int recBuffSize=AudioRecord.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);     //recBuffSize = 4096; //如果語音斷斷續續可以調整buffer size     AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, recBuffSize);                             byte[] buffer = new byte[recBuffSize];     audioRecord.startRecording(); // 开始录音     try {       clientSocket = new DatagramSocket();     } catch (SocketException e) {       e.printStackTrace();     }     InetAddress des = null;     try {       des = InetAddress.getByName("192.168.1.XX");     } catch (UnknownHostException e) {       e.printStackTrace();     }     int port = 3333;     while (true) {       int bufferReadResult = audioRecord.read(buffer, 0, recBuffSize);       packet = new DatagramPacket(buffer,

Android AudioTrack AudioRecord

如何使用 AudioTrack,其實跟AudioRecord差不多, 我們做一個比較 新增一個AudioTrack 跟新增一個AudioRecord幾乎一樣 AudioTrack audioTrack = new AudioTrack( AudioManager.STREAM_MUSIC, SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM); 以下是AudioRecord AudioRecord record = new AudioRecord( MediaRecorder.AudioSource.DEFAULT, SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); AudioTrack多了AudioTrack.MODE_STREAM這個選項。AudioTrack.MODE_STREAM是指串流的資料。AudioTrack.MODE_STATIC是指一次把整個音源檔載入。 兩個類都有bufferSize這個參數。bufferSize 是需要計算的,也可能跟手機的硬體能力有關。所以兩個類都有提供計算的方法。 int bufferSize = AudioRecord.getMinBufferSize( SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); int bufferSize = AudioTrack.getMinBufferSize( SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); 這樣我們可以建一個Thread來讓AudioTrack播串流音樂 void playMusic() {     new Thread(new Runnable() {     @Override     pub

python 找圖自動點擊

需要 import 這幾個 module import cv2 import numpy as np import pyautogui import time 滑鼠點擊 def click_image(image,pos,  action, timestamp,offset=5):     img = cv2.imread(image)     height, width, channels = img.shape     pyautogui.moveTo(pos[0] + offset, pos[1] + ,offset, timestamp)     pyautogui.click(button=action) 圖片尋找 def imagesearch(image, precision=0.8):     im = pyautogui.screenshot()     img_rgb = np.array(im)     img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)     template = cv2.imread(image, 0)     template.shape[::-1]     res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)     min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)     if max_val < precision:         return [-1,-1]     return max_loc #返回圖片座標 使用方式 if __name__ == '__main__':     pp =imagesearch("./1.png") #尋找1.png的圖。(把圖跟程式放同一個目錄下)     click_image("./1.png", pp, "left", 1) #要點右鍵的話,就把"left"改成 "

升級 ubuntu 後 terminal 無法打開

解決方法 試幾個方法,重開機就好,也不知哪一招有效。紀綠如下 先下載一個 knosole 當暫時的 terminal 第一招 把原本的 .bashrc 先備份一下,砍了。重開機再開terminal看看。 第二招 sudo locale-gen --purge   重開機再開terminal看看。   不行的話,再試試   sudo locale-gen sudo localectl set -locale LANG= "en_US.UTF-8"   重開機再開terminal看看。       第三招 sudo apt remove chrome-remote-desktop   重開機再開terminal看看。  

Python 讀 EXCEL

圖片
先 from xlrd import open_workbook 開放excel檔 a.xlsx wk = open_workbook('a.xlsx') 查看有哪些sheet for s in wk.sheets():     print "Sheet: $s has cols: $s and rows: $s" % (s.name, s.ncols, s.nrows) 讀第一個sheet 的每一列的資料 for r in range(wk.sheets()[0].nrows):     print wk.sheets()[0].cell_value(r, 3) #第4欄     print wk.sheets()[0].cell_value(r, 5) #第6欄 如果遇到合併格 s = wk.sheets()[0] table = s.merged_cells merCell = {} for r in range(s.nrows):     for t in table:         if r>=t[0] and r< t[1]:             if s.cell_value(r,0) != "":                 merCells[t] = s.cell_value(r,0) 因為s.merged_cells會給出,sheet中所有合併格範圍的list如下 [(1, 8, 0, 1), (48, 56, 0, 1), (39, 45, 0, 1), (8, 32, 0, 1), (45, 48, 0, 1), (85, 93, 0, 1), (93, 109, 0, 1), (56, 64, 0, 1), (83, 85, 0, 1), (32, 38, 0, 1), (77, 83, 0, 1), (64, 73, 0, 1), (73, 77, 0, 1)] 以第一個元素 (1,8,0,1)是指這個合併格的 row 是      1<= row < 8 , 0<=col < 1這個範圍。 所以我們做一個字典,merCell。以m