常用查詢

      在〈常用查詢〉中尚無留言

取消狀態列及導航列

Android 11需使用getWindow().insetsController取得WindowInsetsController物件controller,然後再使用controller.hide()設定螢幕要隱藏的地方。

WindowInsets.Type.statusBars()為最上方的狀態列,值為1
WindowInsets.Type.navigationBars()為最下方的虛擬按鈕(導航列),值為2

Android 10及以下,就必需使用舊的方法

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {//Android11
var controller: WindowInsetsController? = getWindow().insetsController
controller?.hide(
WindowInsets.Type.statusBars()+
WindowInsets.Type.navigationBars()
)
}
else{//Android10及以下
@Suppress("DEPRECATION")
window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
)
}
}

取消視窗title

在AndroidManifest.xml加入藍色的Theme。
另外screenOrientaiton為設定螢幕的方向。

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<activity android:name=".MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

取消休眠

如果不想讓系統進入 suspend (休眠)狀態,請於 OnCreate()方法新增如下

window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

或是在 Layout 新增如下藍色部份

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    android:keepScreenOn = "true">
 ... 
</RelativeLayout>

Toast

Toast可以彈出一個簡易的訊息,並在固定的時間後自動消失。

Toast.makeText(context, "要顯示的訊息",Toast.LENGTH_SHORT).show()

Toast只可以在指定的Activity中顯示,所以必需傳入 context,也且必需在UI主執行緒中執行。

AlertDialog

AlertDialog可以彈出一個對話方框,裏面可以安排自訂的按鈕。

AlertDialog.Builder(this)
    .setTitle("網路有問題")
    .setMessage("\n1. 手機訊號不良\n2. 內湖伺服器網路斷線\n\n請確認手機訊號, 或稍後重新執行")
    .setPositiveButton("離開", DialogInterface.OnClickListener{ _,_->
        this.finish()
    })
    .show()

查詢網域ip

有了DNS/DDNS,為何還要想要由網域查詢 ip呢! 原因是像華碩路由器所提供的動態轉址功能,時好時壞的。所以如果能第一次先查詢到 ip,後續直接由 ip 來進線的話,就不用怕 DDNS時好時壞的問題了。

首先由 InetAddress傳入網域名稱,再取得 hostName即可取得 ip的字串。

請注意這段程式碼一定要在新 Thread中執行,若使用 UI Thread執行,InetAddress.getByName會取得 null 物件。

fun getIp(){
    Thread {
        try {
            G.ip = InetAddress.getByName(G.hostName).hostName
            handler.sendEmptyMessage(G.HostSuccess)
        }
        catch (e: Exception) {
            handler.sendEmptyMessage(G.HostError)
        }
    }.start()
}

todo

傳送GET資料

Android 大都會使用 Http 協議來訪問網絡, Android 主要提供了兩種方式,分別為 HttpURLConnection及 HttpClient。在Android6.0版本中 HttpClient 已經被移除。而且HttpURLConnection是由 Google所開發,效能高, Bug 少,所以當然是要使用 HttpURLConnection。

先產生 URL物件,再由 url.openConnection產生 HttpURLConnection物件。連線後的結果,可由conn.inputStream進行讀取。

conn.readTimeout=5000 可防止網路臨時中斷而進入孤立連線,單位為ms。也就是說5秒後,沒有取得回應,就會發生 Exception。

當由 conn.inputStream 取得 InputStream 物件時,系統會先自動觸發 conn.connect()函數開始執行連線。然後就可以由 inputStream讀取回應了。

Thread{
try {
val cmd =
"http://${G.ip}/dispatch/delete_case.php?id=%s".format(roadcase["id"])
val url = URL(cmd)
val conn = url.openConnection() as HttpURLConnection
conn.requestMethod = "GET"
conn.readTimeout = 5000
conn.doInput=true
val inputStream = conn.inputStream
val br = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
var lines=StringBuffer()
do{
val line=br.readLine()
if(line==null)break
lines.append(line)
}while(true)
if (lines.contains("success")) {
handler.sendEmptyMessage(What_success)
} else {
handler.sendEmptyMessage(What_delete_error)
}
}
catch(e:Exception){
handler.sendEmptyMessage(What_Internet_error)
}

}.start()

todo

傳送POST資料

POST 則是多了 DataOutputStream 連線,將要傳遞的資料,傳入 dos中。

大部份的網站都說,要傳送純文字資料,必需將 Content-Type 設定為 “application/x-www-form-urlencoded”。但本人測試的結果,要嘛就是不要設定,不然就要設定為 null。

//conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
conn.setRequestProperty("Content-Type", null)

底下為完整代碼

Thread{
    try{
        val url=URL("http://${G.ip}/dispatch/test.php")
        val conn=url.openConnection() as HttpURLConnection
        conn.readTimeout=5000
        conn.connectTimeout=5000
        conn.doInput=true
        conn.doOutput=true
        conn.useCaches=false
        conn.requestMethod="POST"
        conn.setRequestProperty("Connection", "Keep-Alive")
        conn.setRequestProperty("Charset", "utf-8")
        conn.setRequestProperty("Content-Type", null)
        val dos= DataOutputStream(conn.outputStream)
        var sb=StringBuffer()
        sb.append("userAccount=")
        sb.append(URLEncoder.encode("張無忌", "UTF-8"))
        dos.writeBytes(sb.toString())
        val inputStream=conn.inputStream
        val br = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
        var lines=StringBuffer()
        do{
            var line = br.readLine()
            if (line==null)break
            lines.append(line)
        }while(true)

        Log.d("Thomas", lines.toString())
        dos.flush()
        dos.close()
        if (lines.contains("success"))handler.sendEmptyMessage(G.Pothole_upload_success)
        else handler.sendEmptyMessage(G.Pothole_upload_error)
    }
    catch(e:Exception){
        handler.sendEmptyMessage(G.Pothole_upload_timeout)
    }
}.start()

傳送POST圖片

下面的例子,是將圖片讀入,然後寫入到 dos中。至於文字資料,則採用 GET的方式由網址傳入。

val url=URL("http://${G.ip}/dispatch/upload_pothole.php?id=${id}")
Thread{
    try{
        val lineEnd="\r\n"
        val prefix="--"
        val boundary= UUID.randomUUID().toString()
        val maxBufferSize=1*1024*1024
        val file=File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "%s/%s".format(G.photoDir,fileName))
        val fis=FileInputStream(file)
        val conn=url.openConnection() as HttpURLConnection
        conn.readTimeout=5000
        conn.connectTimeout=5000
        conn.doInput=true
        conn.doOutput=true
        conn.useCaches=false
        conn.requestMethod="POST"
        conn.setRequestProperty("Connection", "Keep-Alive")
        conn.setRequestProperty("Charset", "utf-8")
        conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary)
        val dos= DataOutputStream(conn.outputStream)
        dos.writeBytes(prefix + boundary + lineEnd)
        dos.writeBytes(String.format("Content-Disposition: form-data; name=\"file\";filename=\"%s\"%s", fileName, lineEnd))
        dos.writeBytes(lineEnd)
        var bytesAvailable=fis.available()
        var bufferSize=Math.min(bytesAvailable, maxBufferSize)
        val buffer=ByteArray(bufferSize)
        var bytesRead=fis.read(buffer, 0, bufferSize)
        while(bytesRead>0){
            dos.write(buffer, 0, bufferSize)
            bytesAvailable=fis.available()
            bufferSize=Math.min(bytesAvailable, maxBufferSize)
            bytesRead=fis.read(buffer, 0, bufferSize)
        }
        dos.writeBytes(lineEnd)
        dos.writeBytes(prefix + boundary + prefix + lineEnd)
        val inputStream=conn.inputStream
        val br = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
        var lines=StringBuffer()
        do{
            var line = br.readLine()
            if (line==null)break
            lines.append(line)
        }while(true)
        fis.close()
        dos.flush()
        dos.close()
        if (webResponse.contains("success"))handler.sendEmptyMessage(G.Pothole_upload_success)
        else handler.sendEmptyMessage(G.Pothole_upload_error)
    }
    catch(e:Exception){
        handler.sendEmptyMessage(G.Pothole_upload_timeout)
    }
}.start()

todo

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *