A. android平台到底能不能通過串口發送AT指令呢,急!!!
AT命令(Attention)在手機中,用於對modem(也就是移動模塊)通過串口命令進行操作,處理與語音電話、簡訊和數據。
關於AT命令:
Android系統與AT命令
對於智能手機,AP和BP分離的情況,在AP上的系統通過串口和BP通信是個不錯方式。在Android的源碼中有一個內部包com.android.internal.telephony中有對AT命令的封裝和解析,但這種internal的包開發者不能調用的SDK部分,可以用來封裝ROM。這說明Android對AT command的方式是支持的。
對於Android如何調用AT command
用root登錄命令行,直接對串口進行操作,如echo -e "AT " > /dev/smd0
具體的串口,不同設備會有不同,甚至不一定會提供。這種方式,開發者是可以調用的,通過Runtime.exec直接執行命令行命令,但要求是root,例如echo -e "ATD123456789; " > /dev/smd0,撥打123456789的號碼。
目前最新的AT命令標准發布與2014.6.27,似乎還活得挺滋潤的。但是給出的keywords是UMTS, GSM, command, terminal, LTE這說明CDMA確實很可能不是採用AT命令的方式。
B. Android串口通訊
1.打開串口。
2.串口處於監聽狀態
3.想串口寫入數據,串口接收到數據返回數據
SerialPort類所在的包一定要和上圖包名一直,因為串口通訊需要使用jni中的函數。
package android_serialport_api;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import com.fx.serialporttest.L;
public class SerialPort {
/*
* Do not remove or rename the field mFd: it is used by native method
* close();
*/
private FileDescriptor mFd;
private FileInputStream mFileInputStream;
private FileOutputStream mFileOutputStream;
/**
* 構造方法
* @param device 串口地址
* @param baurate 波特率
* @param flags
* @throws IOException
* @throws InterruptedException
*/
public SerialPort(File device,int baudrate,int flags) {
/*
* 檢測是否有訪問許可權
*/
if(!device.canRead()||!device.canWrite()){
//如果沒有讀寫許可權,嘗試chmod命令這個文件
L.tag("沒有讀寫許可權");
Process su;
try {
su = Runtime.getRuntime().exec("/system/bin/su");//獲取root讀寫許可權
String cmd = "chmod 777"+device.getAbsolutePath()+"\n"+"exit\n";
su.getOutputStream().write(cmd.getBytes()); //向此路徑文件寫入命令
if((su.waitFor()!=0||!device.canRead()||!device.canWrite())){
throw new SecurityException();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mFd = open(device.getAbsolutePath(),baudrate,flags);
if(mFd==null){
mFd = open(device.getAbsolutePath(),baudrate,flags);
L.tag("native open return null");
}
mFileInputStream = new FileInputStream(mFd);
mFileOutputStream = new FileOutputStream(mFd);
}
public FileInputStream getmFileInputStream() {
return mFileInputStream;
}
public void setmFileInputStream(FileInputStream mFileInputStream) {
this.mFileInputStream = mFileInputStream;
}
public FileOutputStream getmFileOutputStream() {
return mFileOutputStream;
}
public void setmFileOutputStream(FileOutputStream mFileOutputStream) {
this.mFileOutputStream = mFileOutputStream;
}
//JNI
private native static FileDescriptor open(String path,int baudrate,int flags);
public native void close();
static {
System.loadLibrary("serial_port");
}
}
package android_serialport_api;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import com.fx.serialporttest.L;
public class SerialPortFinger {
private static ReadThread readThread;
private static FileInputStream mFileInputStream;
private static FileOutputStream mFileOutputStream;
static String path = "/dev/ttyS0";//設備主板的串口地址,地址有所不同
public void startListener(){
SerialPort serialPort = new SerialPort(new File(path), 9600, 0);//9600是波特率,這個也是有所不同,具體要看設備
mFileInputStream = serialPort.getmFileInputStream();
mFileOutputStream = serialPort.getmFileOutputStream();//獲取串口寫入流
readThread = new ReadThread();
readThread.start();//開啟監聽
}
/**
* 發送指令到串口
*
* @param cmd
* @return
*/
public boolean sendCmds(String cmd) {
boolean result = true;
byte[] mBuffer = (cmd+"\r\n").getBytes();
try {
if (mFileOutputStream != null) {
mFileOutputStream.write(mBuffer);
} else {
result = false;
}
} catch (IOException e) {
e.printStackTrace();
result = false;
}
return result;
}
static class ReadThread extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
int len;
StringBuffer sb = new StringBuffer("");
while(true){ //循環監聽串口,讀取返回的數據
byte[] buffer = new byte[1024];
if(mFileInputStream==null){
return;
}
try {
len = mFileInputStream.read(buffer);
if(len>0){
sb.append(new String(buffer, 0, len));
}
if(!sb.toString().equals(""))
{
L.tag(sb.toString());//收到串口的返回數據,在日誌中列印出來
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
L.tag("接受完成");
}
}
}
}
C. Android UART 串口通信
最近有項目需要實現windows機器和Android開發版進行UART串口通信,經過3天查找嘗試,特記錄一下最終方案,希望之後的同行少走彎路,最後在git上回開源我最終的方案希望大家支持。
Android 3.0.1
Gradle 4.1
ARM開發版 : RK3399
PC機器:Win10
開發機器:MAC 10.13.3
先上圖
由於 android-serialport-api 項目中的so使用較old的ndk編譯,所以在對於Android 6.0 以上版本兼容的時候會報錯 dlopen failed: "has text relocations" 。且使用的mk進行編譯,特升級為用cmake編譯。
升級 android-serialport-api
項目結構:
app對應原項目中的各個Activity, androidserial 是mole 對應編譯之前的so,還有API的封裝。可以直接引用androidserial,調用方法參考app目錄下的activity。
注意 關於許可權!
當接入開發板後如果發現 Error You do not have read/write permission to the serial port 需要root 許可權 ,在開發者模式中開啟root 許可權 adb和應用
使用一下命令開啟Android對串口的讀寫許可權
setenforce 0 : 關閉防火牆,有人說關鍵是這,但是我的環境不用關閉,只要給許可權就可以
注意 關於ttyS1 - 6 ttyS1 - 6 對應的是 UART 串口1-6 一般都是一一對應的。這個具體要看一下開發板的說明。
記錄的比較糙,還請見諒,如有問題請留言,我看到後肯定回復。項目主要看結構,剩下的都是復制黏貼的事。 git地址:https://github.com/braincs/AndroidSerialLibrary