2018年1月6日 星期六

Android-SQLite 使用 SQLiteOpenHelper (三)_新增資料( Insert )

上一篇有談到如何建立簡單的資料表(Table)
此篇我們要來談
如何創立簡單的新增、修改、刪除、查詢方法
以便於我們後續使用

1 . 新增資料
private static final String KEY_DATE = "count_date";
private static final String KEY_NUMBER = "count_number";
private static final String KEY_NOTE = "count_note";  

/**
 * 添加單筆資料
 *
 * @param mDate
 * @param number
 * @param note
 * @return
 */
public boolean addData(@NonNull Date mDate, int number,
                       String note) {

    ContentValues values = new ContentValues();
    DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    values.put(KEY_DATE, sdf.format(mDate));
    values.put(KEY_NUMBER, number);
    values.put(KEY_NOTE, note);

    // Inserting Row
    SQLiteDatabase db = this.getWritableDatabase();
    return db.insert(TABLE_CONTACTS, null, values) == -1 ? false : true;
}

為什麼 insert 方法欄位有一個 null ?? 這欄位的用途是啥?












nullColumnHack :
簡單來說,SQLite 無法像 SQL 直接放置空值
所以必須給一個欄位名稱讓他產生充滿 null 的一列
還是不了解?那我們來實作一番

這是原本的 Table






我們執行指令後









再次執行指令












如果我們有需要用到此方法
最後一欄一定要 null
public void ...(){
  db.insert(TableName, ColumnName, null);  
}


2018年1月5日 星期五

Android-SQLite 使用 SQLiteOpenHelper (二)_說明

更新日期:20180105

上一篇我們有先規劃我們想要產出的表格
那此篇就開始 簡易教學吧

1 . 首先,繼承 SQLiteOpenHelper
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MyDatabaseHandler extends SQLiteOpenHelper {
    // 必要
    public MyDatabaseHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // 如果資料庫不存在
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
       // 資料庫有任何參數異動
    }
}


2 . SQLiteOpenHelper 須提供的參數









name : DataBase 的名稱。
factory : 若無使用到指標,則預設為 null。
version : 如果版號與先前不同,則會觸發 onUpgrade。

3 . 將上一篇我們所需要的參數提出,並將建構子更改成我們需要的
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "counterManager";

public MyDatabaseHandler(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

4 . 建立我們所需要的 資料表( Table )
備註: Table如果需多個 Table 也在此建立
private static final String TABLE_CONTACTS = "counter";
private static final String KEY_ID = "id";
private static final String KEY_DATE = "count_date";
private static final String KEY_NUMBER = "count_number";
private static final String KEY_NOTE = "count_note";

@Override
public void onCreate(SQLiteDatabase db) {
    // 依照各自需求建立對應的資料表
    // 建立資料庫
    String createDB = "create table " + TABLE_CONTACTS + "(" +
            KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
            KEY_DATE + " DATE UNIQUE NOT NULL," +
            KEY_NUMBER + " int," +
            KEY_NOTE + " char(255)" +
            ");";
    db.execSQL(createDB);
}

5 . 處理版本升級問題
private static final String TABLE_CONTACTS = "counter";

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // 如果資料庫有更新,則移除存在的
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS);
    onCreate(db);
}


先記錄問題
1 . onUpgrade 觸發的實際時機



2017年12月30日 星期六

Java-切割、分割字串

想必各位大大對這需求一定不陌生吧
在此紀錄下來
希望大家一起分享一起交流

切割字串解析成每個字元
1 . 方法一
String s = "abcd,efgh";
System.out.println("Use String method : Char Array");
char[] a = s.toCharArray();
for (char c : a) {
    System.out.println(c);
}

Use String method : Char Array
a
b
c
d
,
e
f
g
h

2 . 方法二
String s = "abcd,efgh";
System.out.println("Use String method : String length and char At");
for (int i = 0; i < s.length(); i++) {
    char c = s.charAt(i);
    System.out.println(c);
}

Use String method : String length and char At
a
b
c
d
,
e
f
g
h

藉由特定的字串切割( Split )
1 . 字串切割
String s = "abcd,efgh";
System.out.println("Use String method : Split");
String[] strs = s.split(",");
for(String str: strs) {
    System.out.println(str);
}

Use String method : Split
abcd
efgh

2 .字串切割,但限制條件
String s = "abcd,efgh,ijkl,mnop,qrst";
System.out.println("Use String method : Split limit");
for (String retval : s.split(",", 3)) {
    System.out.println(retval);
}

Use String method : Split limit
abcd
efgh
ijkl,mnop,qrst

歡迎轉載,請註明出處。




2017年12月26日 星期二

Java-網頁憑證轉為 JKS 格式

1 . 命令提示字元目標移至 C:/.../jdk/bin
2 . 將下載好後的 *.cer 憑證放置此路徑下
3 . 更改以下指令檔案名稱並且執行
keytool -importcert -file <changedCertName>.cer -keystore <exportName>.jks -alias changeit
4 . 產生出來的 jks 會產生再此路徑底下

2017年12月12日 星期二

Android-手機震動(Vibrator)

可能在特定情境下
開發者要讓使用者知道狀態
有時會採用音效、震動模式
讓使用者知道是有觸發的
目前採用 Kotlin 語法,會與 Java 有稍許不同

在此先來記錄
以便之後用的到

思路:
1 . 手機權限存取
2 . 取得對應服務
3 . 設定震動參數

實作開始
1 . 手機權限存取
<uses-permission android:name="android.permission.VIBRATE" />

2 . 取得手機對應服務
var myVibrator = application.getSystemService(Service.VIBRATOR_SERVICE) as Vibrator;

3 . 設定手機震動參數
if (Build.VERSION.SDK_INT >= 26) {
    myVibrator?.vibrate(VibrationEffect.createOneShot(100, 10));
} else {
    myVibrator?.vibrate(100);
}

Source Code
import android.app.Service
import android.os.Build
import android.os.Bundle
import android.os.VibrationEffect
import android.os.Vibrator
import android.support.v7.app.AppCompatActivity
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity(), View.OnClickListener {

    private lateinit var myVibrator1: Vibrator;

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        myVibrator1 = application.getSystemService(Service.VIBRATOR_SERVICE) as Vibrator;

        constraintCounterBackground.setOnClickListener(this);

    }

    override fun onClick(view: View) {
        when (view?.id) {
            R.id.constraintCounterBackground -> {
                println("item found");
                if (Build.VERSION.SDK_INT >= 26) {
                    myVibrator1?.vibrate(VibrationEffect.createOneShot(100, 10));
                } else {
                    myVibrator1?.vibrate(100);
                }
                var intCounterNum = (textCounterNum.text.toString()).toInt();
                textCounterNum.setText((intCounterNum + 1).toString());
            }
            else -> {
                println("item not found");
            }
        }
    }

}



參考資料:
Android-Vibrator
Android學習筆記 - 震動(Vibrator)
Android vibrate is deprecated. How to use VibrationEffect in Android>= API 26?

2017年12月10日 星期日

Android-Kotlin 監聽元件錯誤

近期用 Kotlin 開發 Android 時
會發現非常奇怪的錯誤會發生
通常是在匯入 interface 的時候
比如 View.OnClickListener...等
在此記下
以便於之後查閱

1 . 程式碼在此
package com.xxx.xxx.xxx.xxx

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity(), View.OnClickListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        linearLayout.setOnClickListener(this);

    }

    override fun onClick(view: View) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        when (view?.id) {
            R.id.linearLayout -> {
                println("found");
            }
            else -> println("item not found");
        }

    }

}


2 . 導致錯誤...
Process: com.xxx.xxx.xxx.xxx, PID: 8563
kotlin.NotImplementedError: An operation is not implemented: not implemented
    at com.xxx.xxx.xxx.xxx.MainActivity.onClick(MainActivity.kt:19)
    at android.view.View.performClick(View.java:5637)
    at android.view.View$PerformClick.run(View.java:22429)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6119)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

解法:

去除預設的 TODO("not implemented")
結果程式終於能夠正常執行了

簡單的說法
提醒你要記得實作
但是在 Kotlin 下 TODO 是會起阻擋提醒作用的

參考資料 :
 [Kotlin]kotlin.NotImplementedError: An operation is not implemented: not implemented
NotImplementedError

2017年12月2日 星期六

Android-Logger 和 Log4j 的使用與差異

注意:目前 Log4j 有一些尚未完成,敬請見諒。

此篇語法為 Kotlin,宣告方法類似 Java ,只是順序不同

大家在開發程式的過程中
想必可能要了解或者是要更清楚流向
會用到 System.out.println、Logger、Log4j
此篇用談到如何在 AndroidStudio 用 Java Logger 和 Log4j

1 . 一般 Java Logger 方法
package com.light.blue.log.activity

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import java.util.logging.Level.*
import java.util.logging.Logger

class MainActivity : AppCompatActivity() {

    private val logger: Logger? = Logger.getLogger("MainActivity");

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // SEVERE   嚴重(特高級別)
        // WARNING  注意
        // INFO     訊息

        logger?.info("info message");
        logger?.log(SEVERE, "Server message");
        logger?.log(WARNING, "WARNING message");
        logger?.log(INFO, "INFO message");
        
    }
}