編輯:關於Android編程
(1) 使用Android Studio建立一個沒有Activity的項目,對於一個簡單的輸入法而言,MainActivity並不是必要的,只需要一個輸入法服務即可。因此,該項目mainfest.xml文件可以如下定義:
(2) mainfest.xml文件中使用到了資源文件xml/method,我們需要在res目錄下創建一個文件夾xml,在該文件夾下創建method.xml文件,該文件中包含了輸入法的subtype屬性,輸入法通過該屬性定義它所支持的輸入模式和語言,一個輸入法可以包含多個subtype屬性。
對於一個subtype:
label是該subtype的名字
imeSubtypeLocale是該subtype支持的語言類型
imeSubtypeMode是它所支持的模式,可以是keyboard或者voice,當輸入法被調起是,系統會把用戶選擇的mode值傳給輸入法。這裡,我們只有一個subtype,效果並不明顯。
(3) method.xml中的@string字符串保存在string.xml中,該文件在res/values目錄下,我們需要對其做修改:
AndroidXXIME XXIME 中文
xxime在manifest中定義service的android:label時被引用到,該字串用來顯示系統“語言和輸入法”中本輸入法的名字:

(4) 鍵盤布局
這個簡單的鍵盤中,我們只需要4個按鍵:
在res/layout/中添加文件keyboard.xml,定義鍵盤布局,內容如下:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">
其中keyPreviewLayout表示鍵盤被按下時的布局資源。在res/layout中添加preview.xml如下:
(5) 按鍵信息定義在qwerty.xml文件中,該文件保存在res/xml目錄下:
Row表示一行,內部又包含Key表示一個按鍵,每個按鍵有兩個必填屬性:
· keyLabel:按鍵上顯示的文字
· codes:該按鍵代表的Unicode碼
我們定義的鍵盤布局如下圖所示:

(6) input服務創建
AndroidXXIME類擴展了InputMethodService,並實現了KeyboardView.OnKeyboardActionListener接口。該類的定義如下:
public class AndroidXXIME extends InputMethodService
implements KeyboardView.OnKeyboardActionListener {
private KeyboardView keyboardView; // 對應keyboard.xml中定義的KeyboardView
private Keyboard keyboard; // 對應qwerty.xml中定義的Keyboard
@Override
public void onPress(int primaryCode) {
}
@Override
public void onRelease(int primaryCode) {
}
@Override
public void onText(CharSequence text) {
}
@Override
public void swipeDown() {
}
@Override
public void swipeLeft() {
}
@Override
public void swipeRight() {
}
@Override
public void swipeUp() {
}
@Override
public View onCreateInputView() {
// keyboard被創建後,將調用onCreateInputView函數
keyboardView = (KeyboardView)getLayoutInflater().inflate(R.layout.keyboard, null); // 此處使用了keyboard.xml
keyboard = new Keyboard(this, R.xml.qwerty); // 此處使用了qwerty.xml
keyboardView.setKeyboard(keyboard);
keyboardView.setOnKeyboardActionListener(this);
return keyboardView;
}
private void playClick(int keyCode){
// 點擊按鍵時播放聲音,在onKey函數中被調用
AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE);
switch(keyCode){
case 32:
am.playSoundEffect(AudioManager.FX_KEYPRESS_SPACEBAR);
break;
case Keyboard.KEYCODE_DONE:
case 10:
am.playSoundEffect(AudioManager.FX_KEYPRESS_RETURN);
break;
case Keyboard.KEYCODE_DELETE:
am.playSoundEffect(AudioManager.FX_KEYPRESS_DELETE);
break;
default: am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD);
}
}
@Override
public void onKey(int primaryCode, int[] keyCodes) {
InputConnection ic = getCurrentInputConnection();
playClick(primaryCode);
switch(primaryCode){
case Keyboard.KEYCODE_DELETE :
ic.deleteSurroundingText(1, 0);
break;
case Keyboard.KEYCODE_DONE:
ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
break;
default:
char code = (char)primaryCode;
ic.commitText(String.valueOf(code), 1);
}
}
}
以上內容部分參考了:寫一個Android輸入法01——最簡步驟
我們使用資源文件夾res/raw保存我們的輸入內容,該文件夾需要自己建立,輸入內容的格式如下:
阿壩州 阿東 阿海 阿克蘇地區 阿拉蕾 阿拉斯 阿聯 ……
數據的讀取采用InputStreamReader 和 BufferedReader,具體方法如下:
String res="";
Resources resources=this.getResources();
InputStream is=null;
is=resources.openRawResource(R.raw.keywords);
InputStreamReader reader = new InputStreamReader(is);
BufferedReader breader = new BufferedReader(reader);
數據取到後就存入SQLite數據庫中:
private void createDb()throws IOException{
String res="";
Resources resources=this.getResources();
InputStream is=null;
Integer i=1;
try{
is=resources.openRawResource(R.raw.dongjiahua);
InputStreamReader reader = new InputStreamReader(is);
BufferedReader breader = new BufferedReader(reader);
SQLiteDatabase db = openOrCreateDatabase("keywords", Context.MODE_PRIVATE,null);
db.execSQL("CREATE TABLE IF NOT EXISTS keyword (id integer primary key autoincrement,word varchar(20),searched varchar(5))");
while((res = breader.readLine())!=null){
addData(db,i,res,"no");
i++;
}
breader.close();
reader.close();
db.close();
}catch (IOException e){
e.getStackTrace();
}
}
在某些情況下,需要刪除數據表重新建立:
SQLiteDatabase db = openOrCreateDatabase("keywords", Context.MODE_PRIVATE,null);
db.execSQL("DROP TABLE IF EXISTS keyword");
db.close();
直接執行sql 命令DROP即可。
private String getKeyword() {
SQLiteDatabase db = openOrCreateDatabase("keywords", Context.MODE_PRIVATE,null);
String select = "SELECT id,word FROM KEYWORD WHERE searched=?";
Cursor c = db.rawQuery(select,new String[]{"no"});
String res="";
Integer id=0;
if(c.getCount()==0){
res="no data";
}
if(c.moveToFirst()){
id = c.getInt(0);
res = c.getString(1);
db.delete("keyword","word=?",new String[]{res});
addData(db,id,res,"yes");
}
db.close();
return res;
}
每次只取符合條件的第一條記錄的相關字段,並將該調用信息寫入數據庫中,即把“searched”字段由“no”改為“yes”。
改寫onKey 方法:
public void onKey(int primaryCode, int[] keyCodes){
InputConnection ic = getCurrentInputConnection();
playClick(primaryCode);
switch(primaryCode){
case Keyboard.KEYCODE_DELETE :
try{
createDb();
}catch (IOException e){
e.getStackTrace();
}
break;
case Keyboard.KEYCODE_DONE:
sendKeyChar('\n');
break;
case 32:
SQLiteDatabase db = openOrCreateDatabase("keywords", Context.MODE_PRIVATE,null);
db.execSQL("DROP TABLE IF EXISTS keyword");
db.close();
default:
ic.commitText(getKeyword(), 1);
}
}
當按下create database 時:通過creatDb 方法建立數據庫和數據表,並將數據從raw資源文件中讀取到數據表中;
當按下delete database 時:刪除數據庫中的指定數據表;
當按下INPUT 時:通過getKeyword 方法從數據庫中取得一個數據,提交到文本框中;
當按下DONE 時:向文本框中發送字符’\n’,即回車,微信的搜索開始執行。
Android Bound Service(一) ----- Extending Binder Service(進程內綁定Service的簡單例子)
前言 重新學習這一項技術,主要的原因,是因為以前沒有好好的學,那時總覺得作品能動,能完成工作就好了,而這種得過且過的想法,大大地影響了我的技術程度,也因此,
Android基礎入門教程——9.3 使用Camera拍照
Android基礎入門教程——9.3 使用Camera拍照標簽(空格分隔): Android基礎入門教程本節引言 本節給大家帶來的是Android
Hybrid移動應用:用網頁技術提供Native體驗
移動app可以大致被分為三種,native、hybrid和web app。如果使用native app,你可以使用設備和操作系統的所有能力,同時,平台的性能負荷最小。然而
Android 自定義Button控件實現按鈕點擊變色
效果圖如下所示:一、shape 樣式:(在drawable新建--》new--》Drawable resource file 在父級標簽selector添加Item )&