發表文章

Screen Size 螢幕尺寸 與 文字大小

        DisplayMetrics dm=new DisplayMetrics();         getWindowManager().getDefaultDisplay().getMetrics(dm);         displayWidth=dm.widthPixels;         displayHeight=dm.heightPixels; 用這個方法我們可以得到螢幕的尺寸。有了螢幕的尺寸,我們就可以設定文字的大小,讓文字大小跟著螢幕尺寸改變。 int contentWordSize=11; //一列11個字。 TextView tv=findViewById(R.id.xxxx); tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, displayWidth/contentWordSize); 這樣是不是很方便!

改變 drawable 的顏色

public static Drawable tintDrawable(Drawable drawable, int color) {         Drawable wd = DrawableCompat.wrap(drawable);         DrawableCompat.setTint(wd, color);         return wd;     } 只要將使用中的drawable,用上面的方法處理,再拿來用,drawable的顏色就會改變。 這個方法可以用來處理ImageButton點擊後,ImageButton變色。方便許多。 ImageButton ibtn = findViewById( R.id.xxxx ); iBtn.setBackground(getResources().getDrawable(R .drawable.xxxx )); ibtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ibtn.setBackground(tintDrawable(getResources().getDrawable( R.drawable.xxxx ) .mutate() , Color.Green )); new Handler().postDelayed(new Runnable() { @Override public void run() { iBtn.setBackground(getResources().getDrawable(R .drawable.xxxx )); } }, 1000); } }); 現在ImageButton點擊後,會將原來的圖變成Color.GREEN的

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"改成 "