motify compile link error

motify compile link error
This commit is contained in:
ant 2016-09-18 09:03:25 +08:00
parent 923914edae
commit 03e74a8e50
5418 changed files with 1367914 additions and 206149 deletions

View file

@ -0,0 +1,78 @@
package com.rtk.simpleconfig_wizard;
import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class AESCrypt {
// private static final String TAG = "AESCrypt";
public static String encrypt(String key, String cleartext) throws Exception {
byte[] md5Key = MD5(key.getBytes());
byte[] result = encrypt(md5Key, cleartext.getBytes());
return toHex(result);
}
public static String decrypt(String key, String encrypted) throws Exception {
byte[] md5Key = MD5(key.getBytes());
byte[] result = decrypt(md5Key, toByte(encrypted));
return new String(result);
}
public static byte[] MD5(byte[] key) throws Exception {
byte[] md5_digest = new byte[16];
MessageDigest mDigest;
mDigest = MessageDigest.getInstance("MD5");
mDigest.update(key, 0, key.length);
md5_digest = mDigest.digest();
// System.out.printf("MD5: ");
// for(int i=0; i<16; i++) {
// System.out.printf("%02x ", md5_digest[i]);
// }
// System.out.printf("\n");
return md5_digest;
}
public static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES/ECB/PKCS5Padding");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
public static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES/ECB/PKCS5Padding");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static byte[] toByte(String hexString) {
int len = hexString.length()/2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
return result;
}
public static String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2*buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private final static String HEX = "0123456789ABCDEF";
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
}

View file

@ -0,0 +1,77 @@
package com.rtk.simpleconfig_wizard;
import android.graphics.drawable.Drawable;
public class ConfigurationDevice {
public static class DeviceInfo
{
private int aliveFlag;
private String name;
private String IP;
private String macAdrress;
private int securityType;
private Drawable img;
private boolean connectedflag;
public int getaliveFlag()
{
return this.aliveFlag;
}
public void setaliveFlag(int aliveFlag)
{
this.aliveFlag = aliveFlag;
}
public String getName()
{
return this.name;
}
public void setName(String name)
{
this.name= name;
}
public String getIP()
{
return this.IP;
}
public void setIP(String IP)
{
this.IP= IP;
}
public String getmacAdrress()
{
return this.macAdrress;
}
public void setmacAdrress(String macAdrress)
{
this.macAdrress= macAdrress;
}
public int getsecurityType()
{
return this.securityType;
}
public void setsecurityType(int securityType)
{
this.securityType= securityType;
}
public Drawable getimg()
{
return this.img;
}
public void setimg(Drawable img)
{
this.img= img;
}
public boolean getconnectedflag()
{
return this.connectedflag;
}
public void setconnectedflag(boolean connectedflag)
{
this.connectedflag= connectedflag;
}
}
}

View file

@ -0,0 +1,472 @@
package com.rtk.simpleconfig_wizard;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import android.os.Environment;
import android.util.Log;
public class FileOps {
private static final String TAG = "FileOps";
private String SDPATH = Environment.getExternalStorageDirectory()+"/";
//private String SDPATH = "/data/data/com.realtek.simpleconfig_wizard/files/";
private String CFGFOLDER = "rtk_sc_wizard/";
public static String SsidPasswdFile = "wizard1";
public static String CfgPinFile = "wizard2";
public static String CtlPinFile = "wizard3";
public static String PASSWD;
private boolean checkFileExists(String path) {
File file = new File(path);
return file.exists();
}
private boolean createDir(String dir) {
File dfile = new File(dir);
if(dfile.exists())
return true;
// Log.d(TAG, "createDir: " + dfile);
return dfile.mkdir();
}
private boolean createFile(String file) throws Exception
{
File ffile = new File(file);
// Log.d(TAG, "createFile: " + ffile);
return ffile.createNewFile();
}
// private boolean deleteFile(String file) throws Exception
// {
// File ffile = new File(file);
// Log.d(TAG, "createFile: " + ffile);
// return ffile.delete();
// }
public void SetKey(String key)
{
PASSWD = key;
// Log.d(TAG, "PASSWD: " + PASSWD);
}
public RandomAccessFile openFile(String filename) throws Exception
{
RandomAccessFile rf = null;
String dir = SDPATH + CFGFOLDER;
String file = dir + filename;
// Log.d(TAG, "openFile: " + file);
if(!checkFileExists(file)) {
if(!createDir(dir)) {
//Log.e(TAG, "Create Dir Error");
return null;
}
if(!createFile(file)) {
Log.e(TAG, "Create File Error");
return null;
}
}
rf = new RandomAccessFile(file, "rw");
return rf;
}
public void writeFile(RandomAccessFile rf, String str) throws Exception
{
if(rf==null) {
return;
}
String estr = AESCrypt.encrypt(PASSWD, str);
// Log.d(TAG, "estr: " + estr);
rf.writeBytes(estr);
}
public String readFile(RandomAccessFile rf) throws Exception
{
String str = null;
byte[] strbuf = null;
int len = 0 ;
if(rf==null) {
return null;
}
len = (int)rf.length();
if(len==0) {
return null;
}
strbuf = new byte[len];
rf.read(strbuf, 0, len);
// for(int i=0; i<strbuf.length; i++)
// Log.d(TAG, "" + strbuf[i]);
str = new String(strbuf);
// Log.d(TAG, "read str: " + str);
String dstr = AESCrypt.decrypt(PASSWD, str);
// Log.d(TAG, "decrypt str: " + dstr);
return dstr;
}
public void closeFile(RandomAccessFile rf) throws Exception
{
if(rf==null)
return;
rf.close();
}
public void ParseSsidPasswdFile(String ssid)
{
RandomAccessFile rf = null;
String str = null;
try {
rf = openFile(FileOps.SsidPasswdFile);
} catch (Exception e1) {
e1.printStackTrace();
Log.e(TAG, "Open File Error");
return;
}
try {
str = readFile(rf);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Read File Error");
try {
rf.setLength(0);
} catch (IOException e1) {
e1.printStackTrace();
Log.e(TAG, "Set Length Error");
return;
}
return;
}
// Log.d(TAG, "Read: " + str);
SCCtlOps.StoredPasswd = new String();
if(str==null) {
//Log.e(TAG, "Null File");
} else {
String[] items = str.split("\\|");
for(int i=0; i<items.length; i++) {
// System.out.printf("items[%d]: %s\n", i, items[i]);
String[] subitems = items[i].split("\\:");
// for(int j=0; j<subitems.length; j++) {
// Log.d(TAG, String.format("subitems[%d]: %s\n", j, subitems[j]));
// }
// Log.d(TAG, String.format("Selected SSID: %s\n", ssid));
if(ssid.equals(subitems[0]) && !subitems[1].equals("null")) {
SCCtlOps.StoredPasswd += subitems[1];
// Log.d(TAG, "Find already existed SSID");
break;
}
}
}
try {
closeFile(rf);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Close File Error");
}
}
public void UpdateSsidPasswdFile(boolean isOpenNetwork)
{
RandomAccessFile rf;
try {
rf = openFile(FileOps.SsidPasswdFile);
} catch (Exception e2) {
e2.printStackTrace();
Log.e(TAG, "Open File Error");
return;
}
long len=0;
boolean isOld = false;
String getstr = new String();
String setstr = new String();
try {
len = rf.length();
} catch (IOException e1) {
e1.printStackTrace();
Log.e(TAG, "Get Length Error");
return;
}
if(len>0) {
try {
getstr = readFile(rf);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Read File Error");
return;
}
// Log.d(TAG, "getstr: " + getstr);
String[] items = getstr.split("\\|");
for(int i=0; i<items.length; i++) {
// System.out.printf("items[%d]: %s\n", i, items[i]);
String[] subitems = items[i].split("\\:");
// for(int j=0; j<subitems.length; j++) {
// System.out.printf("subitems[%d]: %s\n", j, subitems[j]);
// }
if(SCCtlOps.ConnectedSSID.equals(subitems[0])) {
isOld = true;
// Log.d(TAG, "Refresh old");
if(isOpenNetwork)
setstr += SCCtlOps.ConnectedSSID + ":null|";
else
setstr += SCCtlOps.ConnectedSSID + ":" + SCCtlOps.ConnectedPasswd + "|";
} else {
// Log.d(TAG, "Re-Add existed");
setstr += subitems[0] + ":" + subitems[1] + "|";
}
}
}
if(!isOld) {
// Log.d(TAG, "Add new");
if(isOpenNetwork)
setstr += SCCtlOps.ConnectedSSID + ":null|";
else
setstr += SCCtlOps.ConnectedSSID + ":" + SCCtlOps.ConnectedPasswd + "|";
}
// Log.d(TAG, "setstr: " + setstr);
try {
rf.seek(0); //re-write all info
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "Re-Seek Error");
return;
}
try {
writeFile(rf, setstr);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Write File Error");
return;
}
try {
closeFile(rf);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Close File Error");
return;
}
}
public String ParseCfgPinFile()
{
RandomAccessFile rf = null;
String getstr = null;
try {
rf = openFile(FileOps.CfgPinFile);
} catch (Exception e1) {
e1.printStackTrace();
Log.e(TAG, "Open File Error");
return null;
}
try {
getstr = readFile(rf);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Read File Error");
try {
rf.setLength(0);
} catch (IOException e1) {
e1.printStackTrace();
Log.e(TAG, "Set Length Error");
return null;
}
return null;
}
// Log.d(TAG, "Read: " + getstr);
try {
closeFile(rf);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Close File Error");
}
return getstr;
}
public void UpdateCfgPinFile(String pin)
{
RandomAccessFile rf;
try {
rf = openFile(FileOps.CfgPinFile);
} catch (Exception e2) {
e2.printStackTrace();
Log.e(TAG, "Open File Error");
return;
}
try {
writeFile(rf, pin);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Write File Error");
return;
}
try {
closeFile(rf);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Close File Error");
return;
}
}
public String ParseCtlPinFile(String mac)
{
RandomAccessFile rf = null;
String getstr = null;
String pin = null;
try {
rf = openFile(FileOps.CtlPinFile);
} catch (Exception e1) {
e1.printStackTrace();
Log.e(TAG, "Open File Error");
return null;
}
try {
getstr = readFile(rf);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Read File Error");
try {
rf.setLength(0);
} catch (IOException e1) {
e1.printStackTrace();
Log.e(TAG, "Set Length Error");
return null;
}
return null;
}
// Log.d(TAG, "Read: " + getstr);
if(getstr==null) {
//Log.e(TAG, "Null File");
} else {
String[] items = getstr.split("\\;");
for(int i=0; i<items.length; i++) {
// System.out.printf("items[%d]: %s\n", i, items[i]);
String[] subitems = items[i].split("\\|");
// for(int j=0; j<subitems.length; j++) {
// Log.d(TAG, String.format("subitems[%d]: %s\n", j, subitems[j]));
// }
// Log.d(TAG, String.format("Selected MAC: %s\n", mac));
if(mac.equals(subitems[0]) && !subitems[1].equals("null")) {
pin = subitems[1];
// Log.d(TAG, "Find PIN");
break;
}
}
}
try {
closeFile(rf);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Close File Error");
}
return pin;
}
public void UpdateCtlPinFile(String mac, String pin)
{
RandomAccessFile rf;
try {
rf = openFile(FileOps.CtlPinFile);
} catch (Exception e2) {
e2.printStackTrace();
Log.e(TAG, "Open File Error");
return;
}
long len=0;
boolean isOld = false;
String getstr = new String();
String setstr = new String();
try {
len = rf.length();
} catch (IOException e1) {
e1.printStackTrace();
Log.e(TAG, "Get Length Error");
return;
}
if(len>0) {
try {
getstr = readFile(rf);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Read File Error");
return;
}
// Log.d(TAG, "getstr: " + getstr);
String[] items = getstr.split("\\;");
for(int i=0; i<items.length; i++) {
// System.out.printf("items[%d]: %s\n", i, items[i]);
String[] subitems = items[i].split("\\|");
// for(int j=0; j<subitems.length; j++) {
// System.out.printf("subitems[%d]: %s\n", j, subitems[j]);
// }
if(mac.equals(subitems[0])) {
isOld = true;
// Log.d(TAG, "Refresh old");
setstr += subitems[0] + "|" + pin + ";";
} else {
// Log.d(TAG, "Re-Add existed");
setstr += subitems[0] + "|" + subitems[1] + ";";
}
}
}
if(!isOld) {
// Log.d(TAG, "Add new");
setstr += mac + "|" + pin + ";";
}
// Log.d(TAG, "setstr: " + setstr);
try {
rf.seek(0); //re-write all info
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "Re-Seek Error");
return;
}
try {
writeFile(rf, setstr);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Write File Error");
return;
}
try {
closeFile(rf);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Close File Error");
return;
}
}
}

View file

@ -0,0 +1,505 @@
package com.rtk.simpleconfig_wizard;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import android.net.wifi.ScanResult;
import android.util.Log;
public class SCCtlOps {
private static final String TAG = "SCCtlOps";
public static boolean IsOpenNetwork = false; // Default has password, not open network
public static String ConnectedSSID; // Connected WIFI's SSID
public static String ConnectedBSSID; // Connected WIFI's BSSID
public static String ConnectedPasswd; // Connected WIFI's Password
public static String StoredPasswd;
public static boolean isHiddenSSID;
public static boolean addNewNetwork;
public static ScanResult reBuiltScanResult;
public static final int MAX_CLIENTS_NUM = 32;
public static boolean DiscoveredNew;
public static boolean SetAble = true;
/** For UDP Data Receive */
// public static byte[] RecvBuf = new byte[512];
/** UDP Payload Format Flag */
public static class Flag{
private Flag(){
}
/** Flag */
public static final int Version = (0x00<<6); // 2 bits
public static final int RequestFlag = (0<<5); // 1 bit
public static final int ResponseFlag = (1<<5);
/** Request */
public static final int Discover = 0x00; // 5 bits
public static final int SaveProf = 0x01;
public static final int DelProf = 0x02;
public static final int RenameDev = 0x03;
public static final int ReturnACK = 0x04;
/** Response */
public static final int CfgSuccessACK = 0x00; // 5 bits
public static final int DiscoverACK = 0x01;
public static final int SaveProfACK = 0x02;
public static final int DelProfACK = 0x03;
public static final int RenameDevACK = 0x04;
public static final int CfgSuccessACKSendBack = 0x05;
public static final int CfgSuccessACKFinish = 0x06;
}
/** UDP Payload Format ACK to Scan */
public static class ScanACK{
private ScanACK(){
}
/** MAC */
public static int MaxDevNum = 0;
public static byte[][] Mac = new byte[MAX_CLIENTS_NUM][6]; // Record the connected STA
/** Status */
public static byte[] Status = new byte[MAX_CLIENTS_NUM];
/** Device Type */
public static byte[][] Type = new byte[MAX_CLIENTS_NUM][2];
/** Device IP */
public static byte[][] IPBuf = new byte[MAX_CLIENTS_NUM][4];
public static String[] IP = new String[MAX_CLIENTS_NUM];
/** Device Name */
public static byte[][] NameBuf = new byte[MAX_CLIENTS_NUM][64];
public static String[] Name = new String[MAX_CLIENTS_NUM];
/** Use PIN or Not */
public static Boolean[] UsePin = new Boolean[MAX_CLIENTS_NUM];
}
public static byte[] rtk_sc_gen_digest(byte[] inputData)
{
try {
return AESCrypt.MD5(inputData);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void rtk_sc_control_reset()
{
ScanACK.MaxDevNum = 0;
Arrays.fill(ScanACK.Status, (byte)0);
for(int i=0; i<MAX_CLIENTS_NUM; i++) {
Arrays.fill(ScanACK.Mac[i], (byte)0);
Arrays.fill(ScanACK.Type[i], (byte)0);
Arrays.fill(ScanACK.IPBuf[i], (byte)0);
Arrays.fill(ScanACK.NameBuf[i], (byte)0);
}
ScanACK.IP = new String[MAX_CLIENTS_NUM];
ScanACK.Name = new String[MAX_CLIENTS_NUM];
}
public static byte[] rtk_sc_gen_discover_packet(String defaultPIN)
{
byte[] CmdBuf = new byte[92];
short PayloadLen = 0;
Arrays.fill(CmdBuf, (byte)0);
/** Flag */
CmdBuf[0] += Flag.Version;
CmdBuf[0] += Flag.RequestFlag;
CmdBuf[0] += Flag.Discover;
/** Encrypt Flag */
CmdBuf[3] = 0x01;
PayloadLen += 1;
/** Nonce */
if(CmdBuf[3] == 0x01) {
for(int i=0; i<64; i++) {
Random r = new Random();
CmdBuf[4+i] = (byte) (r.nextInt(256) + 1);
}
}
PayloadLen += 64;
/** Default PIN Digest */
byte[] inputData = new byte[64 + defaultPIN.length()];
System.arraycopy(CmdBuf, 4, inputData, 0, 64);
System.arraycopy(defaultPIN.getBytes(), 0, inputData, 64, defaultPIN.length());
byte[] digest = rtk_sc_gen_digest(inputData);
System.arraycopy(digest, 0, CmdBuf, PayloadLen+3, 16);
PayloadLen += 16;
/** MAC Address */
PayloadLen += 6;
/** Device Type */
PayloadLen += 2;
/** Length */
byte[] buf = new byte[2];
buf[0] = (byte)((PayloadLen >> 8) & 0xff);
buf[1] = (byte)(PayloadLen & 0xff);
System.arraycopy(buf, 0, CmdBuf, 1, 2);
/*String dbgStr = new String();
for(int i=0; i<92; i++)
dbgStr += String.format("%02x ", CmdBuf[i]);
Log.d(TAG, "Client Discover Packet: " + dbgStr);*/
return CmdBuf;
}
public static byte[] rtk_sc_gen_control_packet(int flag, String defaultPIN, String inputPIN, String nameStr)
{
byte[] CmdBuf;
short PayloadLen = 0;
byte[] digest;
byte[] inputData;
byte[] nameBuf = null;
if(flag == Flag.RenameDev) {
// Log.d(TAG, "nameStr: " + nameStr);
try {
nameBuf = nameStr.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Get name bytes error");
e.printStackTrace();
return null;
}
CmdBuf = new byte[100+nameBuf.length];
} else {
CmdBuf = new byte[100];
}
Arrays.fill(CmdBuf, (byte)0);
/** Flag */
CmdBuf[0] += Flag.Version;
CmdBuf[0] += Flag.RequestFlag;
CmdBuf[0] += flag;
/** Encrypt Flag */
CmdBuf[3] = 0x01;
PayloadLen += 1;
/** Nonce */
if(CmdBuf[3] == 0x01) {
for(int i=0; i<64; i++) {
Random r = new Random();
CmdBuf[4+i] = (byte) (r.nextInt(256) + 1);
}
}
PayloadLen += 64;
/** Default PIN Digest */
// Log.d(TAG, "defaultPIN: " + defaultPIN);
inputData = new byte[64 + defaultPIN.length()];
System.arraycopy(CmdBuf, 4, inputData, 0, 64);
System.arraycopy(defaultPIN.getBytes(), 0, inputData, 64, defaultPIN.length());
digest = rtk_sc_gen_digest(inputData);
System.arraycopy(digest, 0, CmdBuf, PayloadLen+3, 16);
PayloadLen += 16;
/** User Input PIN Digest */
// Log.d(TAG, "inputPIN: " + inputPIN);
inputData = new byte[64 + inputPIN.length()];
System.arraycopy(CmdBuf, 4, inputData, 0, 64);
System.arraycopy(inputPIN.getBytes(), 0, inputData, 64, inputPIN.length());
digest = rtk_sc_gen_digest(inputData);
System.arraycopy(digest, 0, CmdBuf, PayloadLen+3, 16);
PayloadLen += 16;
/** Device Name */
if(flag == Flag.RenameDev) {
// String tmp = new String();
// for(int i=0; i<nameBuf.length; i++) {
// tmp += String.format("%02x ", nameBuf[i]);
// }
// Log.d(TAG, "nameBuf: " + tmp);
System.arraycopy(nameBuf, 0, CmdBuf, PayloadLen+3, nameBuf.length);
PayloadLen += nameBuf.length;
}
/** Length */
byte[] buf = new byte[2];
buf[0] = (byte)((PayloadLen >> 8) & 0xff);
buf[1] = (byte)(PayloadLen & 0xff);
System.arraycopy(buf, 0, CmdBuf, 1, 2);
return CmdBuf;
}
public static byte[] rtk_sc_gen_control_confirm_packet(int flag, String defaultPIN, String inputPIN)
{
byte[] CmdBuf;
short PayloadLen = 0;
byte[] digest;
byte[] inputData;
CmdBuf = new byte[101];
Arrays.fill(CmdBuf, (byte)0);
/** Flag */
CmdBuf[0] += Flag.Version;
CmdBuf[0] += Flag.RequestFlag;
CmdBuf[0] += Flag.ReturnACK;
/** Encrypt Flag */
CmdBuf[3] = 0x01;
PayloadLen += 1;
/** Nonce */
if(CmdBuf[3] == 0x01) {
for(int i=0; i<64; i++) {
Random r = new Random();
CmdBuf[4+i] = (byte) (r.nextInt(256) + 1);
}
}
PayloadLen += 64;
/** Default PIN Digest */
// Log.d(TAG, "defaultPIN: " + defaultPIN);
inputData = new byte[64 + defaultPIN.length()];
System.arraycopy(CmdBuf, 4, inputData, 0, 64);
System.arraycopy(defaultPIN.getBytes(), 0, inputData, 64, defaultPIN.length());
digest = rtk_sc_gen_digest(inputData);
System.arraycopy(digest, 0, CmdBuf, PayloadLen+3, 16);
PayloadLen += 16;
/** User Input PIN Digest */
// Log.d(TAG, "inputPIN: " + inputPIN);
inputData = new byte[64 + inputPIN.length()];
System.arraycopy(CmdBuf, 4, inputData, 0, 64);
System.arraycopy(inputPIN.getBytes(), 0, inputData, 64, inputPIN.length());
digest = rtk_sc_gen_digest(inputData);
System.arraycopy(digest, 0, CmdBuf, PayloadLen+3, 16);
PayloadLen += 16;
/** Encrypt Flag */
CmdBuf[PayloadLen+3] += flag;
PayloadLen += 1;
/** Length */
byte[] buf = new byte[2];
buf[0] = (byte)((PayloadLen >> 8) & 0xff);
buf[1] = (byte)(PayloadLen & 0xff);
System.arraycopy(buf, 0, CmdBuf, 1, 2);
return CmdBuf;
}
public static int handle_discover_ack(byte[] recv_buf)
{
int length, equalCnt=0;
String dbgStr;
if(SetAble==false)
return -1;
DiscoveredNew = false;
// System.arraycopy(recv_buf, 0, RecvBuf, 0, recv_buf.length);
length = (recv_buf[1]<<8)&0xFF00 | (recv_buf[2])&0xFF;
// Log.d(TAG, String.format("length: 0x%02x", length));
if(length < 6) {
Log.e(TAG, "At least a mac\n");
return -1;
}
if(ScanACK.MaxDevNum > MAX_CLIENTS_NUM) {
Log.e(TAG, "The receive buf is full\n");
return -1;
}
/** Judge if it is the same MAC */
// Log.d(TAG, "Max Device Number: " + ScanACK.MaxDevNum);
if(ScanACK.MaxDevNum > 0) {/* Not the first time */
for(int j=0; j<ScanACK.MaxDevNum; j++) {
for(int i=0; i<6; i++) {
if(recv_buf[3+i] == ScanACK.Mac[j][i])
equalCnt++;
}
if(equalCnt == 6)
return -1; //find the same MAC
equalCnt = 0; //for the second judge(if has)
}
}
/** Not the same MAC */
System.arraycopy(recv_buf, 3, ScanACK.Mac[ScanACK.MaxDevNum], 0, 6);
dbgStr = new String();
for(int i=0; i<6; i++) {
dbgStr += String.format("%02x", ScanACK.Mac[ScanACK.MaxDevNum][i]);
if(i<5)
dbgStr += ":";
}
Log.i(TAG, "Discovered MAC: " + dbgStr);
/** Status */
if(length >= 7) {
ScanACK.Status[ScanACK.MaxDevNum] = recv_buf[9];
// Log.d(TAG, String.format("Status: %02x", ScanACK.Status[ScanACK.MaxDevNum]));
}
/** Device Type */
if(length >= 9) {
System.arraycopy(recv_buf, 10, ScanACK.Type[ScanACK.MaxDevNum], 0, 2);
// Log.d(TAG, String.format("Device Type: %02x %02x", ScanACK.DevType[ScanACK.MaxDevNum][0],
// ScanACK.DevType[ScanACK.MaxDevNum][1]));
}
/** Device IP */
if(length >= 13) {
System.arraycopy(recv_buf, 12, ScanACK.IPBuf[ScanACK.MaxDevNum], 0, 4);
ScanACK.IP[ScanACK.MaxDevNum] = String.format("%d.%d.%d.%d",
ScanACK.IPBuf[ScanACK.MaxDevNum][0]&0xff,
ScanACK.IPBuf[ScanACK.MaxDevNum][1]&0xff,
ScanACK.IPBuf[ScanACK.MaxDevNum][2]&0xff,
ScanACK.IPBuf[ScanACK.MaxDevNum][3]&0xff);
Log.i(TAG, "Device IP: " + ScanACK.IP[ScanACK.MaxDevNum]);
}
/** Device Name */
if(length >= 77) {
System.arraycopy(recv_buf, 16, ScanACK.NameBuf[ScanACK.MaxDevNum], 0, 64);
String name = null;
try {
name = new String(ScanACK.NameBuf[ScanACK.MaxDevNum], "UTF-8").trim();
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Get device name error");
e.printStackTrace();
}
if(name.length()>0)
ScanACK.Name[ScanACK.MaxDevNum] = name;
else
ScanACK.Name[ScanACK.MaxDevNum] = null;
Log.i(TAG, "Device Name: " + ScanACK.Name[ScanACK.MaxDevNum]);
}
/** Use PIN or Not */
if(length >= 78) {
ScanACK.UsePin[ScanACK.MaxDevNum] = (recv_buf[80]>0) ? true:false;
// Log.d(TAG, "UsePin: " + ScanACK.UsePin[ScanACK.MaxDevNum]);
}
ScanACK.MaxDevNum++;
DiscoveredNew = true;
return 0;
}
public static int rtk_sc_get_discovered_dev_num()
{
return ScanACK.MaxDevNum;
}
// public static void rtk_get_connected_dev_test1()
// {
// /** For test */
// byte[] tmp = {0x21,
// 00,0x2c,
// 00,0x18,(byte)0x95,0x61,(byte)0x89,0x75,
// 0x01,
// 00,0x01,
// (byte)0xc0,(byte)0xa8,0x01,(byte)0xdd,00,
// (byte)0xe7,(byte)0xa9,(byte)0xba,(byte)0xe8,(byte)0xb0,
// (byte)0x83,00,00,00,00,
// 00,00,00,00,00,
// 00,00,00,00,00,
// 00,00,00,00,00,
// 00,00};
// System.arraycopy(tmp, 0, RecvBuf, 0, tmp.length);
// handle_discover_ack();
// }
//
// public static void rtk_get_connected_dev_test2()
// {
// byte[] tmp = {0x21,
// 00,0x2c,
// 00,0x44,0x46,0x66,0x66,0x76,
// 0x02,
// 00,0x02,
// (byte)0xc0,(byte)0xa8,0x01,(byte)0xde,00,
// 0x54,0x56,00,00,00,
// 00,00,00,00,00,
// 00,00,00,00,00,
// 00,00,00,00,00,
// 00,00,00,00,00,
// 00,00};
// System.arraycopy(tmp, 0, RecvBuf, 0, tmp.length);
// handle_discover_ack();
// }
public static int rtk_sc_get_discovered_dev_info(List<HashMap<String, Object>> DevInfo)
{
int i;
String buf;
HashMap<String, Object> hmap;
SetAble = false;
// Log.d(TAG, "ScanACK.MaxDevNum: " + ScanACK.MaxDevNum);
for(int index=0; index<ScanACK.MaxDevNum; index++) {
buf = new String();
hmap = new HashMap<String, Object>();
for(i=0; i<6; i++) {
buf += String.format("%02x", ScanACK.Mac[index][i]);
if(i<5)
buf += ":";
}
// Log.d(TAG, "Mac: " + buf);
hmap.put("MAC", buf);
buf = new String();
switch(ScanACK.Status[index]) {
case 0x01:
buf = "Connected";
break;
case 0x02:
buf = "Profile saved";
break;
default:
buf = "Unkown status";
break;
}
// Log.d(TAG, "Status: " + buf);
hmap.put("Status", buf);
buf = new String();
short type = (short)((ScanACK.Type[index][0]&0xff<<8) + (ScanACK.Type[index][1]&0xff) );
switch(type) {
case 0x0000:
buf = "Any type";
break;
case 0x0001:
buf = "TV";
break;
case 0x0002:
buf = "Air conditioner";
break;
default:
buf = "Unkown type";
break;
}
// Log.d(TAG, "DevType: " + buf);
hmap.put("Type", buf);
// Log.d(TAG, "IP: " + ScanACK.DevIP[index]);
hmap.put("IP", ScanACK.IP[index]);
// Log.d(TAG, "Name: " + ScanACK.DevName[index]);
hmap.put("Name", ScanACK.Name[index]);
// Log.d(TAG, "PIN: " + ScanACK.UsePin[index]);
hmap.put("PIN", ScanACK.UsePin[index]);
DevInfo.add(hmap);
}
SetAble = true;
return 0;
}
}

View file

@ -0,0 +1,116 @@
/*
* Wifi Connecter
*
* Copyright (c) 20101 Kevin Yuan (farproc@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**/
package com.wifi.connection;
import com.rtk.simpleconfig_wizard.R;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.provider.Settings;
import android.text.InputType;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.CompoundButton.OnCheckedChangeListener;
public abstract class BaseContent implements Floating.Content, OnCheckedChangeListener {
protected final WifiManager mWifiManager;
protected final Floating mFloating;
protected final ScanResult mScanResult;
protected final String mScanResultSecurity;
protected final boolean mIsOpenNetwork ;
protected int mNumOpenNetworksKept;
protected View mView;
protected OnClickListener mCancelOnClick = new OnClickListener() {
@Override
public void onClick(View v) {
mFloating.finish();
}
};
protected String getCancelString() {
return mFloating.getString(android.R.string.cancel);
}
private static final int[] SIGNAL_LEVEL = {R.string.wifi_signal_0, R.string.wifi_signal_1,
R.string.wifi_signal_2, R.string.wifi_signal_3};
public BaseContent(final Floating floating, final WifiManager wifiManager, final ScanResult scanResult) {
super();
mWifiManager = wifiManager;
mFloating = floating;
mScanResult = scanResult;
mScanResultSecurity = Wifi.ConfigSec.getScanResultSecurity(mScanResult);
mIsOpenNetwork = Wifi.ConfigSec.isOpenNetwork(mScanResultSecurity);
mView = View.inflate(mFloating, R.layout.base_content, null);
((TextView)mView.findViewById(R.id.SignalStrength_TextView)).setText(SIGNAL_LEVEL[WifiManager.calculateSignalLevel(mScanResult.level, SIGNAL_LEVEL.length)]);
final String rawSecurity = Wifi.ConfigSec.getDisplaySecirityString(mScanResult);
final String readableSecurity = Wifi.ConfigSec.isOpenNetwork(rawSecurity) ? mFloating.getString(R.string.wifi_security_open) : rawSecurity;
((TextView)mView.findViewById(R.id.Security_TextView)).setText(readableSecurity);
((CheckBox)mView.findViewById(R.id.ShowPassword_CheckBox)).setOnCheckedChangeListener(this);
mNumOpenNetworksKept = Settings.Secure.getInt(floating.getContentResolver(),
Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT, 10);
}
@Override
public View getView() {
return mView;
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
((EditText)mView.findViewById(R.id.Password_EditText)).setInputType(
InputType.TYPE_CLASS_TEXT |
(isChecked ? InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
:InputType.TYPE_TEXT_VARIATION_PASSWORD));
}
public OnClickListener mChangePasswordOnClick = new OnClickListener() {
@Override
public void onClick(View v) {
changePassword();
}
};
public void changePassword() {
mFloating.setContent(new ChangePasswordContent(mFloating, mWifiManager, mScanResult));
}
}

View file

@ -0,0 +1,122 @@
/*
* Wifi Connecter
*
* Copyright (c) 20101 Kevin Yuan (farproc@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**/
package com.wifi.connection;
import com.rtk.simpleconfig_wizard.R;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class ChangePasswordContent extends BaseContent {
private ChangingAwareEditText mPasswordEditText;
public ChangePasswordContent(Floating floating, WifiManager wifiManager,
ScanResult scanResult) {
super(floating, wifiManager, scanResult);
mView.findViewById(R.id.Status).setVisibility(View.GONE);
mView.findViewById(R.id.Speed).setVisibility(View.GONE);
mView.findViewById(R.id.IPAddress).setVisibility(View.GONE);
mPasswordEditText = ((ChangingAwareEditText)mView.findViewById(R.id.Password_EditText));
((TextView)mView.findViewById(R.id.Password_TextView)).setText(R.string.please_type_passphrase);
((EditText)mView.findViewById(R.id.Password_EditText)).setHint(R.string.wifi_password_unchanged);
}
@Override
public int getButtonCount() {
return 2;
}
@Override
public OnClickListener getButtonOnClickListener(int index) {
return mOnClickListeners[index];
}
@Override
public CharSequence getButtonText(int index) {
switch(index) {
case 0:
return mFloating.getString(R.string.wifi_save_config);
case 1:
return getCancelString();
default:
return null;
}
}
@Override
public CharSequence getTitle() {
return mScanResult.SSID;
}
private OnClickListener mSaveOnClick = new OnClickListener() {
@Override
public void onClick(View v) {
if(mPasswordEditText.getChanged()) {
final WifiConfiguration config = Wifi.getWifiConfiguration(mWifiManager, mScanResult, mScanResultSecurity);
boolean saveResult = false;
if(config != null) {
saveResult = Wifi.changePasswordAndConnect(mFloating, mWifiManager, config
, mPasswordEditText.getText().toString()
, mNumOpenNetworksKept);
}
if(!saveResult) {
Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
}
}
mFloating.finish();
}
};
OnClickListener mOnClickListeners[] = {mSaveOnClick, mCancelOnClick};
@Override
public boolean onContextItemSelected(MenuItem item) {
return false;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
}
}

View file

@ -0,0 +1,47 @@
/*
* Wifi Connecter
*
* Copyright (c) 20101 Kevin Yuan (farproc@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**/
package com.wifi.connection;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.EditText;
public class ChangingAwareEditText extends EditText {
public ChangingAwareEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
private boolean mChanged = false;
public boolean getChanged() {
return mChanged;
}
protected void onTextChanged (CharSequence text, int start, int before, int after) {
mChanged = true;
}
}

View file

@ -0,0 +1,35 @@
package com.wifi.connection;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
public abstract class ConfigurationSecurities {
/**
* @return The security of a given {@link WifiConfiguration}.
*/
public abstract String getWifiConfigurationSecurity(WifiConfiguration wifiConfig);
/**
* @return The security of a given {@link ScanResult}.
*/
public abstract String getScanResultSecurity(ScanResult scanResult);
/**
* Fill in the security fields of WifiConfiguration config.
* @param config The object to fill.
* @param security If is OPEN, password is ignored.
* @param password Password of the network if security is not OPEN.
*/
public abstract void setupSecurity(WifiConfiguration config, String security, final String password);
public abstract void setupSecurity_directly(WifiConfiguration config, String security, final String password);
public abstract String getDisplaySecirityString(final ScanResult scanResult);
public abstract boolean isOpenNetwork(final String security);
public static ConfigurationSecurities newInstance() {
// System.out.printf("Version.SDK: %d\n", Version.SDK);
if(Version.SDK < 8) {
return new ConfigurationSecuritiesOld();
} else {
return new ConfigurationSecuritiesV8();
}
}
}

View file

@ -0,0 +1,233 @@
package com.wifi.connection;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.GroupCipher;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.PairwiseCipher;
import android.net.wifi.WifiConfiguration.Protocol;
import android.text.TextUtils;
import android.util.Log;
public class ConfigurationSecuritiesOld extends ConfigurationSecurities {
// Constants used for different security types
public static final String WPA2 = "WPA2";
public static final String WPA = "WPA";
public static final String WEP = "WEP";
public static final String OPEN = "Open";
// For EAP Enterprise fields
public static final String WPA_EAP = "WPA-EAP";
public static final String IEEE8021X = "IEEE8021X";
public static final String[] EAP_METHOD = { "PEAP", "TLS", "TTLS" };
public static final int WEP_PASSWORD_AUTO = 0;
public static final int WEP_PASSWORD_ASCII = 1;
public static final int WEP_PASSWORD_HEX = 2;
static final String[] SECURITY_MODES = { WEP, WPA, WPA2, WPA_EAP, IEEE8021X };
private static final String TAG = "ConfigurationSecuritiesOld";
@Override
public String getWifiConfigurationSecurity(WifiConfiguration wifiConfig) {
if (wifiConfig.allowedKeyManagement.get(KeyMgmt.NONE)) {
// If we never set group ciphers, wpa_supplicant puts all of them.
// For open, we don't set group ciphers.
// For WEP, we specifically only set WEP40 and WEP104, so CCMP
// and TKIP should not be there.
if (!wifiConfig.allowedGroupCiphers.get(GroupCipher.CCMP)
&&
(wifiConfig.allowedGroupCiphers.get(GroupCipher.WEP40)
|| wifiConfig.allowedGroupCiphers.get(GroupCipher.WEP104))) {
return WEP;
} else {
return OPEN;
}
} else if (wifiConfig.allowedProtocols.get(Protocol.RSN)) {
return WPA2;
} else if (wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
return WPA_EAP;
} else if (wifiConfig.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
return IEEE8021X;
} else if (wifiConfig.allowedProtocols.get(Protocol.WPA)) {
return WPA;
} else {
Log.w(TAG, "Unknown security type from WifiConfiguration, falling back on open.");
return OPEN;
}
}
@Override
public String getScanResultSecurity(ScanResult scanResult) {
final String cap = scanResult.capabilities;
for (int i = SECURITY_MODES.length - 1; i >= 0; i--) {
if (cap.contains(SECURITY_MODES[i])) {
return SECURITY_MODES[i];
}
}
return OPEN;
}
@Override
public String getDisplaySecirityString(final ScanResult scanResult) {
return getScanResultSecurity(scanResult);
}
private static boolean isHexWepKey(String wepKey) {
final int len = wepKey.length();
// WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)
if (len != 10 && len != 26 && len != 58) {
return false;
}
return isHex(wepKey);
}
private static boolean isHex(String key) {
for (int i = key.length() - 1; i >= 0; i--) {
final char c = key.charAt(i);
if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f')) {
return false;
}
}
return true;
}
@Override
public void setupSecurity(WifiConfiguration config, String security, final String password) {
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
if (TextUtils.isEmpty(security)) {
security = OPEN;
Log.w(TAG, "Empty security, assuming open");
}
if (security.equals(WEP)) {
int wepPasswordType = WEP_PASSWORD_AUTO;
// If password is empty, it should be left untouched
if (!TextUtils.isEmpty(password)) {
if (wepPasswordType == WEP_PASSWORD_AUTO) {
if (isHexWepKey(password)) {
config.wepKeys[0] = password;
} else {
config.wepKeys[0] = Wifi.convertToQuotedString(password);
}
} else {
config.wepKeys[0] = wepPasswordType == WEP_PASSWORD_ASCII
? Wifi.convertToQuotedString(password)
: password;
}
}
config.wepTxKeyIndex = 0;
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
config.allowedKeyManagement.set(KeyMgmt.NONE);
config.allowedGroupCiphers.set(GroupCipher.WEP40);
config.allowedGroupCiphers.set(GroupCipher.WEP104);
} else if (security.equals(WPA) || security.equals(WPA2)){
config.allowedGroupCiphers.set(GroupCipher.TKIP);
config.allowedGroupCiphers.set(GroupCipher.CCMP);
config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
config.allowedPairwiseCiphers.set(PairwiseCipher.CCMP);
config.allowedPairwiseCiphers.set(PairwiseCipher.TKIP);
config.allowedProtocols.set(security.equals(WPA2) ? Protocol.RSN : Protocol.WPA);
// If password is empty, it should be left untouched
if (!TextUtils.isEmpty(password)) {
if (password.length() == 64 && isHex(password)) {
// Goes unquoted as hex
config.preSharedKey = password;
} else {
// Goes quoted as ASCII
config.preSharedKey = Wifi.convertToQuotedString(password);
}
}
} else if (security.equals(OPEN)) {
config.allowedKeyManagement.set(KeyMgmt.NONE);
} else if (security.equals(WPA_EAP) || security.equals(IEEE8021X)) {
config.allowedGroupCiphers.set(GroupCipher.TKIP);
config.allowedGroupCiphers.set(GroupCipher.CCMP);
if (security.equals(WPA_EAP)) {
config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
} else {
config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
}
if (!TextUtils.isEmpty(password)) {
config.preSharedKey = Wifi.convertToQuotedString(password);
}
}
}
@Override
public void setupSecurity_directly(WifiConfiguration config, String security, final String password) {
if (TextUtils.isEmpty(security)) {
security = OPEN;
Log.w(TAG, "Empty security, assuming open");
}
if (security.equals(WEP)) {
int wepPasswordType = WEP_PASSWORD_AUTO;
// If password is empty, it should be left untouched
if (!TextUtils.isEmpty(password)) {
if (wepPasswordType == WEP_PASSWORD_AUTO) {
if (isHexWepKey(password)) {
config.wepKeys[0] = password;
} else {
config.wepKeys[0] = Wifi.convertToQuotedString(password);
}
} else {
config.wepKeys[0] = wepPasswordType == WEP_PASSWORD_ASCII
? Wifi.convertToQuotedString(password)
: password;
}
}
config.wepTxKeyIndex = 0;
} else if (security.equals(WPA) || security.equals(WPA2)){
// If password is empty, it should be left untouched
if (!TextUtils.isEmpty(password)) {
if (password.length() == 64 && isHex(password)) {
// Goes unquoted as hex
config.preSharedKey = password;
} else {
// Goes quoted as ASCII
config.preSharedKey = Wifi.convertToQuotedString(password);
}
}
} else if (security.equals(OPEN)) {
} else if (security.equals(WPA_EAP) || security.equals(IEEE8021X)) {
if (!TextUtils.isEmpty(password)) {
config.preSharedKey = Wifi.convertToQuotedString(password);
}
}
}
@Override
public boolean isOpenNetwork(String security) {
return OPEN.equals(security);
}
}

View file

@ -0,0 +1,225 @@
package com.wifi.connection;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.util.Log;
public class ConfigurationSecuritiesV8 extends ConfigurationSecurities {
static final int SECURITY_NONE = 0;
static final int SECURITY_WEP = 1;
static final int SECURITY_PSK = 2;
static final int SECURITY_EAP = 3;
enum PskType {
UNKNOWN,
WPA,
WPA2,
WPA_WPA2
}
private static final String TAG = "ConfigurationSecuritiesV14";
private static int getSecurity(WifiConfiguration config) {
if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
return SECURITY_PSK;
}
if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
return SECURITY_EAP;
}
return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
}
private static int getSecurity(ScanResult result) {
if (result.capabilities.contains("WEP")) {
return SECURITY_WEP;
} else if (result.capabilities.contains("PSK")) {
return SECURITY_PSK;
} else if (result.capabilities.contains("EAP")) {
return SECURITY_EAP;
}
return SECURITY_NONE;
}
@Override
public String getWifiConfigurationSecurity(WifiConfiguration wifiConfig) {
return String.valueOf(getSecurity(wifiConfig));
}
@Override
public String getScanResultSecurity(ScanResult scanResult) {
return String.valueOf(getSecurity(scanResult));
}
@Override
public void setupSecurity(WifiConfiguration config, String security, String password) {
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
final int sec = security == null ? SECURITY_NONE : Integer.valueOf(security);
final int passwordLen = password == null ? 0 : password.length();
switch (sec) {
case SECURITY_NONE:
config.allowedKeyManagement.set(KeyMgmt.NONE);
break;
case SECURITY_WEP:
config.allowedKeyManagement.set(KeyMgmt.NONE);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
if (passwordLen != 0) {
// WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
if ((passwordLen == 10 || passwordLen == 26 || passwordLen == 58) &&
password.matches("[0-9A-Fa-f]*")) {
config.wepKeys[0] = password;
} else {
config.wepKeys[0] = '"' + password + '"';
}
}
break;
case SECURITY_PSK:
config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
if (passwordLen != 0) {
if (password.matches("[0-9A-Fa-f]{64}")) {
config.preSharedKey = password;
} else {
config.preSharedKey = '"' + password + '"';
}
}
break;
case SECURITY_EAP:
config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
// config.eap.setValue((String) mEapMethodSpinner.getSelectedItem());
//
// config.phase2.setValue((mPhase2Spinner.getSelectedItemPosition() == 0) ? "" :
// "auth=" + mPhase2Spinner.getSelectedItem());
// config.ca_cert.setValue((mEapCaCertSpinner.getSelectedItemPosition() == 0) ? "" :
// KEYSTORE_SPACE + Credentials.CA_CERTIFICATE +
// (String) mEapCaCertSpinner.getSelectedItem());
// config.client_cert.setValue((mEapUserCertSpinner.getSelectedItemPosition() == 0) ?
// "" : KEYSTORE_SPACE + Credentials.USER_CERTIFICATE +
// (String) mEapUserCertSpinner.getSelectedItem());
// config.private_key.setValue((mEapUserCertSpinner.getSelectedItemPosition() == 0) ?
// "" : KEYSTORE_SPACE + Credentials.USER_PRIVATE_KEY +
// (String) mEapUserCertSpinner.getSelectedItem());
// config.identity.setValue((mEapIdentityView.length() == 0) ? "" :
// mEapIdentityView.getText().toString());
// config.anonymous_identity.setValue((mEapAnonymousView.length() == 0) ? "" :
// mEapAnonymousView.getText().toString());
// if (mPasswordView.length() != 0) {
// config.password.setValue(mPasswordView.getText().toString());
// }
break;
default:
Log.e(TAG, "Invalid security type: " + sec);
}
// config.proxySettings = mProxySettings;
// config.ipAssignment = mIpAssignment;
// config.linkProperties = new LinkProperties(mLinkProperties);
}
@Override
public void setupSecurity_directly(WifiConfiguration config, String security, String password) {
final int sec = security == null ? SECURITY_NONE : Integer.valueOf(security);
final int passwordLen = password == null ? 0 : password.length();
switch (sec) {
case SECURITY_NONE:
break;
case SECURITY_WEP:
if (passwordLen != 0) {
// WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
if ((passwordLen == 10 || passwordLen == 26 || passwordLen == 58) &&
password.matches("[0-9A-Fa-f]*")) {
config.wepKeys[0] = password;
} else {
config.wepKeys[0] = '"' + password + '"';
}
}
break;
case SECURITY_PSK:
if (passwordLen != 0) {
if (password.matches("[0-9A-Fa-f]{64}")) {
config.preSharedKey = password;
} else {
config.preSharedKey = '"' + password + '"';
}
}
break;
case SECURITY_EAP:
break;
default:
Log.e(TAG, "Invalid security type: " + sec);
}
// config.proxySettings = mProxySettings;
// config.ipAssignment = mIpAssignment;
// config.linkProperties = new LinkProperties(mLinkProperties);
}
private static PskType getPskType(ScanResult result) {
boolean wpa = result.capabilities.contains("WPA-PSK");
boolean wpa2 = result.capabilities.contains("WPA2-PSK");
if (wpa2 && wpa) {
return PskType.WPA_WPA2;
} else if (wpa2) {
return PskType.WPA2;
} else if (wpa) {
return PskType.WPA;
} else {
Log.w(TAG, "Received abnormal flag string: " + result.capabilities);
return PskType.UNKNOWN;
}
}
@Override
public String getDisplaySecirityString(final ScanResult scanResult) {
final int security = getSecurity(scanResult);
if(security == SECURITY_PSK) {
switch(getPskType(scanResult)) {
case WPA:
return "WPA";
case WPA_WPA2:
case WPA2:
return "WPA2";
default:
return "?";
}
} else {
switch(security) {
case SECURITY_NONE:
return "OPEN";
case SECURITY_WEP:
return "WEP";
case SECURITY_EAP:
return "EAP";
}
}
return "?";
}
@Override
public boolean isOpenNetwork(String security) {
return String.valueOf(SECURITY_NONE).equals(security);
}
}

View file

@ -0,0 +1,171 @@
/*
* Wifi Connecter
*
* Copyright (c) 20101 Kevin Yuan (farproc@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**/
package com.wifi.connection;
import com.rtk.simpleconfig_wizard.R;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.Toast;
public class ConfiguredNetworkContent extends BaseContent {
public ConfiguredNetworkContent(Floating floating, WifiManager wifiManager,
ScanResult scanResult) {
super(floating, wifiManager, scanResult);
mView.findViewById(R.id.Status).setVisibility(View.GONE);
mView.findViewById(R.id.Speed).setVisibility(View.GONE);
mView.findViewById(R.id.IPAddress).setVisibility(View.GONE);
mView.findViewById(R.id.Password).setVisibility(View.GONE);
}
@Override
public int getButtonCount() {
return 3;
}
@Override
public OnClickListener getButtonOnClickListener(int index) {
switch(index) {
case 0:
return mConnectOnClick;
case 1:
if(mIsOpenNetwork) {
return mForgetOnClick;
} else {
return mOpOnClick;
}
case 2:
return mCancelOnClick;
default:
return null;
}
}
@Override
public CharSequence getButtonText(int index) {
switch(index) {
case 0:
return mFloating.getString(R.string.connect);
case 1:
if(mIsOpenNetwork) {
return mFloating.getString(R.string.forget_network);
} else {
return mFloating.getString(R.string.buttonOp);
}
case 2:
return getCancelString();
default:
return null;
}
}
@Override
public CharSequence getTitle() {
return mFloating.getString(R.string.wifi_connect_to, mScanResult.SSID);
}
private OnClickListener mConnectOnClick = new OnClickListener() {
@Override
public void onClick(View v) {
final WifiConfiguration config = Wifi.getWifiConfiguration(mWifiManager, mScanResult, mScanResultSecurity);
boolean connResult = false;
if(config != null) {
connResult = Wifi.connectToConfiguredNetwork(mFloating, mWifiManager, config, false);
}
if(!connResult) {
Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
}
mFloating.finish();
}
};
private OnClickListener mOpOnClick = new OnClickListener() {
@Override
public void onClick(View v) {
mFloating.registerForContextMenu(v);
mFloating.openContextMenu(v);
mFloating.unregisterForContextMenu(v);
}
};
private OnClickListener mForgetOnClick = new OnClickListener() {
@Override
public void onClick(View v) {
forget();
}
};
private void forget() {
final WifiConfiguration config = Wifi.getWifiConfiguration(mWifiManager, mScanResult, mScanResultSecurity);
boolean result = false;
if(config != null) {
result = mWifiManager.removeNetwork(config.networkId)
&& mWifiManager.saveConfiguration();
}
if(!result) {
Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
}
mFloating.finish();
}
private static final int MENU_FORGET = 0;
private static final int MENU_CHANGE_PASSWORD = 1;
@Override
public boolean onContextItemSelected(MenuItem item) {
switch(item.getItemId()) {
case MENU_FORGET:
forget();
break;
case MENU_CHANGE_PASSWORD:
changePassword();
break;
}
return false;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
menu.add(Menu.NONE, MENU_FORGET, Menu.NONE, R.string.forget_network);
menu.add(Menu.NONE, MENU_CHANGE_PASSWORD, Menu.NONE, R.string.wifi_change_password);
}
}

View file

@ -0,0 +1,163 @@
/*
* Wifi Connecter
*
* Copyright (c) 20101 Kevin Yuan (farproc@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**/
package com.wifi.connection;
import com.rtk.simpleconfig_wizard.R;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
public class CurrentNetworkContent extends BaseContent {
private static final String TAG = "CurrentNetworkContent";
public CurrentNetworkContent(Floating floating, WifiManager wifiManager,
ScanResult scanResult) {
super(floating, wifiManager, scanResult);
mView.findViewById(R.id.Status).setVisibility(View.GONE);
mView.findViewById(R.id.Speed).setVisibility(View.GONE);
mView.findViewById(R.id.IPAddress).setVisibility(View.GONE);
mView.findViewById(R.id.Password).setVisibility(View.GONE);
final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
if(wifiInfo == null) {
Log.d(TAG, "Get WifiInfo Failed\n");
Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
} else {
Log.d(TAG, "Get WifiInfo Ok\n");
final SupplicantState state = wifiInfo.getSupplicantState();
final NetworkInfo.DetailedState detailedState = WifiInfo.getDetailedStateOf(state);
if(detailedState == NetworkInfo.DetailedState.CONNECTED
|| (detailedState == NetworkInfo.DetailedState.OBTAINING_IPADDR && wifiInfo.getIpAddress() != 0)) {
mView.findViewById(R.id.Status).setVisibility(View.VISIBLE);
mView.findViewById(R.id.Speed).setVisibility(View.VISIBLE);
mView.findViewById(R.id.IPAddress).setVisibility(View.VISIBLE);
((TextView)mView.findViewById(R.id.Status_TextView)).setText(R.string.status_connected);
((TextView)mView.findViewById(R.id.LinkSpeed_TextView)).setText(wifiInfo.getLinkSpeed() + " " + WifiInfo.LINK_SPEED_UNITS);
((TextView)mView.findViewById(R.id.IPAddress_TextView)).setText(getIPAddress(wifiInfo.getIpAddress()));
} else if(detailedState == NetworkInfo.DetailedState.AUTHENTICATING
|| detailedState == NetworkInfo.DetailedState.CONNECTING
|| detailedState == NetworkInfo.DetailedState.OBTAINING_IPADDR) {
mView.findViewById(R.id.Status).setVisibility(View.VISIBLE);
((TextView)mView.findViewById(R.id.Status_TextView)).setText(R.string.status_connecting);
}
}
}
@Override
public int getButtonCount() {
// No Modify button for open network.
return mIsOpenNetwork ? 2 : 3;
}
@Override
public OnClickListener getButtonOnClickListener(int index) {
if(mIsOpenNetwork && index == 1) {
// No Modify button for open network.
// index 1 is Cancel(index 2).
return mOnClickListeners[2];
}
return mOnClickListeners[index];
}
@Override
public CharSequence getButtonText(int index) {
switch(index) {
case 0:
return mFloating.getString(R.string.forget_network);
case 1:
if(mIsOpenNetwork) {
// No Modify button for open network.
// index 1 is Cancel.
return getCancelString();
}
return mFloating.getString(R.string.button_change_password);
case 2:
return getCancelString();
default:
return null;
}
}
@Override
public CharSequence getTitle() {
return mScanResult.SSID;
}
private OnClickListener mForgetOnClick = new OnClickListener() {
@Override
public void onClick(View v) {
final WifiConfiguration config = Wifi.getWifiConfiguration(mWifiManager, mScanResult, mScanResultSecurity);
boolean result = false;
if(config != null) {
result = mWifiManager.removeNetwork(config.networkId)
&& mWifiManager.saveConfiguration();
}
if(!result) {
Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
}
mFloating.finish();
}
};
private OnClickListener mOnClickListeners[] = {mForgetOnClick, mChangePasswordOnClick, mCancelOnClick};
private String getIPAddress(int address) {
StringBuilder sb = new StringBuilder();
sb.append(address & 0x000000FF).append(".")
.append((address & 0x0000FF00) >> 8).append(".")
.append((address & 0x00FF0000) >> 16).append(".")
.append((address & 0xFF000000L) >> 24);
return sb.toString();
}
@Override
public boolean onContextItemSelected(MenuItem item) {
return false;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
}
}

View file

@ -0,0 +1,138 @@
/*
* Wifi Connecter
*
* Copyright (c) 20101 Kevin Yuan (farproc@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**/
package com.wifi.connection;
import com.rtk.simpleconfig_wizard.R;
import android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
//import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.TextView;
/**
* A dialog-like floating activity
* @author Kevin Yuan
*
*/
public class Floating extends Activity {
// private static final String TAG = "Floating";
private static final int[] BUTTONS = {R.id.button1, R.id.button2, R.id.button3};
private View mView;
private ViewGroup mContentViewContainer;
private Content mContent;
@Override
public void onCreate(Bundle savedInstanceState) {
// It will not work if we setTheme here.
// Please add android:theme="@android:style/Theme.Dialog" to any descendant class in AndroidManifest.xml!
// See http://code.google.com/p/android/issues/detail?id=4394
setTheme(android.R.style.Theme_Dialog);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
mView = View.inflate(this, R.layout.floating, null);
final DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
mView.setMinimumWidth(Math.min(dm.widthPixels, dm.heightPixels) - 20);
setContentView(mView);
mContentViewContainer = (ViewGroup) mView.findViewById(R.id.content);
}
private void setDialogContentView(final View contentView) {
// Log.d(TAG, "setDialogContentView\n");
mContentViewContainer.removeAllViews();
//mContentViewContainer.addView(contentView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
/* FILL_PARENT is renamed MATCH_PARENT in API Level 8 and higher */
mContentViewContainer.addView(contentView, new LayoutParams(LayoutParams.MATCH_PARENT , LayoutParams.WRAP_CONTENT));
}
public void setContent(Content content) {
mContent = content;
refreshContent();
}
public void refreshContent() {
// Log.d(TAG, "refreshContent");
setDialogContentView(mContent.getView());
((TextView)findViewById(R.id.title)).setText(mContent.getTitle()); //getTitle
final int btnCount = mContent.getButtonCount();
if(btnCount > BUTTONS.length) {
throw new RuntimeException(String.format("%d exceeds maximum button count: %d!", btnCount, BUTTONS.length));
}
findViewById(R.id.buttons_view).setVisibility(btnCount > 0 ? View.VISIBLE : View.GONE);
for(int buttonId:BUTTONS) {
final Button btn = (Button) findViewById(buttonId);
btn.setOnClickListener(null);
btn.setVisibility(View.GONE);
}
for(int btnIndex = 0; btnIndex < btnCount; btnIndex++){
final Button btn = (Button)findViewById(BUTTONS[btnIndex]);
// Log.d(TAG, "getButtonText(" + btnIndex + "): " + mContent.getButtonText(btnIndex));
btn.setText(mContent.getButtonText(btnIndex));
btn.setVisibility(View.VISIBLE);
btn.setOnClickListener(mContent.getButtonOnClickListener(btnIndex));
}
}
public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
if(mContent != null) {
mContent.onCreateContextMenu(menu, v, menuInfo);
}
}
public boolean onContextItemSelected (MenuItem item) {
if(mContent != null) {
return mContent.onContextItemSelected(item);
}
return false;
}
public interface Content {
CharSequence getTitle();
View getView();
int getButtonCount();
CharSequence getButtonText(int index);
OnClickListener getButtonOnClickListener(int index);
void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo);
boolean onContextItemSelected (MenuItem item);
}
}

View file

@ -0,0 +1,124 @@
/*
* Wifi Connecter
*
* Copyright (c) 20101 Kevin Yuan (farproc@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**/
package com.wifi.connection;
import com.rtk.simpleconfig_wizard.R;
import com.rtk.simpleconfig_wizard.SCCtlOps;
import android.content.Intent;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
//import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
//import android.util.Log;
import android.widget.Toast;
public class MainActivity extends Floating {
// private static final String TAG = "WifiMainActivity";
public static final String EXTRA_HOTSPOT = "com.wifi.connection.HOTSPOT";
private ScanResult mScanResult;
private Floating.Content mContent;
private WifiManager mWifiManager;
@Override
protected void onNewIntent (Intent intent) {
setIntent(intent);
// This activity has "singleInstance" launch mode.
// Update content to reflect the newest intent.
doNewIntent(intent);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mWifiManager = (WifiManager)getSystemService(WIFI_SERVICE);
doNewIntent(getIntent());
}
private boolean isAdHoc(final ScanResult scanResule) {
return scanResule.capabilities.indexOf("IBSS") != -1;
}
private void doNewIntent(final Intent intent) {
if(SCCtlOps.addNewNetwork)
mScanResult = SCCtlOps.reBuiltScanResult;
else
mScanResult = intent.getParcelableExtra(EXTRA_HOTSPOT);
// Log.i(TAG, "mScanResult: " + mScanResult);
// Log.d(TAG, "mScanResult.SSID: " + mScanResult.SSID);
// Log.d(TAG, "mScanResult.BSSID: " + mScanResult.BSSID);
// Log.d(TAG, "mScanResult.capabilities: " + mScanResult.capabilities);
// Log.d(TAG, "mScanResult.level: " + mScanResult.level);
// Log.d(TAG, "mScanResult.frequency: " + mScanResult.frequency);
if(mScanResult == null) {
Toast.makeText(this, "No data in Intent!", Toast.LENGTH_LONG).show();
finish();
return;
}
if(isAdHoc(mScanResult)) {
Toast.makeText(this, R.string.adhoc_not_supported_yet, Toast.LENGTH_LONG).show();
finish();
return;
}
final String security = Wifi.ConfigSec.getScanResultSecurity(mScanResult);
final WifiConfiguration config = Wifi.getWifiConfiguration(mWifiManager, mScanResult, security);
if(config != null) {
// Log.d(TAG, "Remove already configured network\n");
mWifiManager.removeNetwork(config.networkId);
}
// Log.d(TAG, "NewNetworkContent\n");
mContent = new NewNetworkContent(this, mWifiManager, mScanResult);
// if(config == null) {
// Log.d(TAG, "NewNetworkContent\n");
// mContent = new NewNetworkContent(this, mWifiManager, mScanResult);
// } else {
// final boolean isCurrentNetwork_ConfigurationStatus = config.status == WifiConfiguration.Status.CURRENT;
// final WifiInfo info = mWifiManager.getConnectionInfo();
// final boolean isCurrentNetwork_WifiInfo = info != null
// && android.text.TextUtils.equals(info.getSSID(), mScanResult.SSID)
// && android.text.TextUtils.equals(info.getBSSID(), mScanResult.BSSID);
// if(isCurrentNetwork_ConfigurationStatus || isCurrentNetwork_WifiInfo) {
// Log.d(TAG, "CurrentNetworkContent\n");
// mContent = new CurrentNetworkContent(this, mWifiManager, mScanResult);
// } else {
// Log.d(TAG, "ConfiguredNetworkContent\n");
// mContent = new ConfiguredNetworkContent(this, mWifiManager, mScanResult);
// }
// }
setContent(mContent);
}
}

View file

@ -0,0 +1,146 @@
/*
* Wifi Connecter
*
* Copyright (c) 20101 Kevin Yuan (farproc@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**/
package com.wifi.connection;
import com.rtk.simpleconfig_wizard.R;
import com.rtk.simpleconfig_wizard.SCCtlOps;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
//import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;
public class NewNetworkContent extends BaseContent {
// private static final String TAG = "NewNetworkContent";
private boolean mIsOpenNetwork = false;
public NewNetworkContent(final Floating floating, final WifiManager wifiManager, ScanResult scanResult) {
super(floating, wifiManager, scanResult);
mView.findViewById(R.id.Status).setVisibility(View.GONE);
mView.findViewById(R.id.Speed).setVisibility(View.GONE);
mView.findViewById(R.id.IPAddress).setVisibility(View.GONE);
if(Wifi.ConfigSec.isOpenNetwork(mScanResultSecurity)) {
mIsOpenNetwork = true;
mView.findViewById(R.id.Password).setVisibility(View.GONE);
} else {
((TextView)mView.findViewById(R.id.Password_TextView)).setText(R.string.please_type_passphrase);
((EditText)mView.findViewById(R.id.Password_EditText)).setText(SCCtlOps.StoredPasswd); //The last password hint
}
}
private OnClickListener mConnectOnClick = new OnClickListener() {
@Override
public void onClick(View v) {
SCCtlOps.ConnectedSSID = mScanResult.SSID; // Store SSID
// Log.d(TAG, "SSID£º" + mScanResult.SSID);
boolean connResult = false;
if(mIsOpenNetwork) {
SCCtlOps.IsOpenNetwork = true;
connResult = Wifi.connectToNewNetwork(mFloating, mWifiManager, mScanResult, null, mNumOpenNetworksKept);
} else {
SCCtlOps.IsOpenNetwork = false;
String passwd = ((EditText)mView.findViewById(R.id.Password_EditText)).getText().toString();
connResult = Wifi.connectToNewNetwork(mFloating, mWifiManager, mScanResult
, passwd
, mNumOpenNetworksKept);
if(connResult) {
SCCtlOps.ConnectedPasswd = new String(passwd); // Store password
// Log.d(TAG, "Password£º" + passwd);
}
}
// if(!connResult) {
// Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
// }
mFloating.finish();
// /** Update SSID and password */
// if(connResult) {
// FileOps fileOps = new FileOps();
// fileOps.UpdateSsidPasswdFile(mIsOpenNetwork);
// }
}
};
private OnClickListener mOnClickListeners[] = {mConnectOnClick, mCancelOnClick};
@Override
public int getButtonCount() {
return 2;
}
@Override
public OnClickListener getButtonOnClickListener(int index) {
return mOnClickListeners[index];
}
@Override
public CharSequence getButtonText(int index) {
switch(index) {
case 0:
return mFloating.getText(R.string.connect);
case 1:
return mFloating.getText(R.string.cancel);
// return getCancelString();
default:
return null;
}
}
@Override
public CharSequence getTitle() {
return mFloating.getString(R.string.wifi_connect_to, mScanResult.SSID);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
return false;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
}
}

View file

@ -0,0 +1,102 @@
/*
* Wifi Connecter
*
* Copyright (c) 20101 Kevin Yuan (farproc@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**/
package com.wifi.connection;
import java.util.List;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.IBinder;
public class ReenableAllApsWhenNetworkStateChanged {
public static void schedule(final Context ctx) {
ctx.startService(new Intent(ctx, BackgroundService.class));
}
private static void reenableAllAps(final Context ctx) {
final WifiManager wifiMgr = (WifiManager)ctx.getSystemService(Context.WIFI_SERVICE);
final List<WifiConfiguration> configurations = wifiMgr.getConfiguredNetworks();
if(configurations != null) {
for(final WifiConfiguration config:configurations) {
wifiMgr.enableNetwork(config.networkId, false);
}
}
}
public static class BackgroundService extends Service {
private boolean mReenabled;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if(WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
final NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
final NetworkInfo.DetailedState detailed = networkInfo.getDetailedState();
if(detailed != NetworkInfo.DetailedState.DISCONNECTED
&& detailed != NetworkInfo.DetailedState.DISCONNECTING
&& detailed != NetworkInfo.DetailedState.SCANNING) {
if(!mReenabled) {
mReenabled = true;
reenableAllAps(context);
stopSelf();
}
}
}
}
};
private IntentFilter mIntentFilter;
@Override
public IBinder onBind(Intent intent) {
return null; // We need not bind to it at all.
}
@Override
public void onCreate() {
super.onCreate();
mReenabled = false;
mIntentFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(mReceiver, mIntentFilter);
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}
}

View file

@ -0,0 +1,29 @@
package com.wifi.connection;
import java.lang.reflect.Field;
import android.os.Build.VERSION;;
/**
* Get Android version in different Android versions. :)
* @author yuanxiaohui
*
*/
public class Version {
public final static int SDK = get();
private static int get() {
final Class<VERSION> versionClass = VERSION.class;
try {
// First try to read the recommended field android.os.Build.VERSION.SDK_INT.
final Field sdkIntField = versionClass.getField("SDK_INT");
return sdkIntField.getInt(null);
//} catch (NoSuchFieldException e) {
// If SDK_INT does not exist, read the deprecated field SDK.
// return Integer.valueOf(VERSION.SDK);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,364 @@
/*
* Wifi Connecter
*
* Copyright (c) 20101 Kevin Yuan (farproc@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**/
package com.wifi.connection;
import java.util.Comparator;
import java.util.List;
import com.rtk.simpleconfig_wizard.SCCtlOps;
import android.content.Context;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.text.TextUtils;
import android.util.Log;
public class Wifi {
public static final ConfigurationSecurities ConfigSec = ConfigurationSecurities.newInstance();
private static final String TAG = "Wifi Connecter";
/**
* Change the password of an existing configured network and connect to it
* @param wifiMgr
* @param config
* @param newPassword
* @return
*/
public static boolean changePasswordAndConnect(final Context ctx, final WifiManager wifiMgr, final WifiConfiguration config, final String newPassword, final int numOpenNetworksKept) {
ConfigSec.setupSecurity(config, ConfigSec.getWifiConfigurationSecurity(config), newPassword);
final int networkId = wifiMgr.updateNetwork(config);
if(networkId == -1) {
// Update failed.
return false;
}
// Force the change to apply.
wifiMgr.disconnect();
return connectToConfiguredNetwork(ctx, wifiMgr, config, true);
}
public static boolean changePasswordAndConnect_directly(final Context ctx, final WifiManager wifiMgr, final WifiConfiguration config, final String newPassword, final int numOpenNetworksKept) {
ConfigSec.setupSecurity_directly(config, ConfigSec.getWifiConfigurationSecurity(config), newPassword);
final int networkId = wifiMgr.updateNetwork(config);
if(networkId == -1) {
// Update failed.
return false;
}
// Force the change to apply.
wifiMgr.disconnect();
return connectToConfiguredNetwork(ctx, wifiMgr, config, true);
}
/**
* Configure a network, and connect to it.
* @param wifiMgr
* @param scanResult
* @param password Password for secure network or is ignored.
* @return
*/
public static boolean connectToNewNetwork(final Context ctx, final WifiManager wifiMgr, final ScanResult scanResult, final String password, final int numOpenNetworksKept) {
final String security = ConfigSec.getScanResultSecurity(scanResult);
if(ConfigSec.isOpenNetwork(security)) {
checkForExcessOpenNetworkAndSave(wifiMgr, numOpenNetworksKept);
}
WifiConfiguration config = new WifiConfiguration();
if(SCCtlOps.isHiddenSSID)
config.hiddenSSID = true;
config.SSID = convertToQuotedString(scanResult.SSID);
if(!SCCtlOps.isHiddenSSID)
config.BSSID = scanResult.BSSID;
ConfigSec.setupSecurity(config, security, password);
int id = -1;
try {
id = wifiMgr.addNetwork(config);
} catch(NullPointerException e) {
Log.e(TAG, "Weird!! Really!! What's wrong??", e);
// Weird!! Really!!
// This exception is reported by user to Android Developer Console(https://market.android.com/publish/Home)
}
if(id == -1) {
return false;
}
if(!wifiMgr.saveConfiguration()) {
return false;
}
config = getWifiConfiguration(wifiMgr, config, security);
if(config == null) {
return false;
}
return connectToConfiguredNetwork(ctx, wifiMgr, config, true);
}
public static boolean connectToNewNetwork_directly(final Context ctx, final WifiManager wifiMgr, final ScanResult scanResult, final String password, final int numOpenNetworksKept) {
final String security = ConfigSec.getScanResultSecurity(scanResult);
if(ConfigSec.isOpenNetwork(security)) {
checkForExcessOpenNetworkAndSave(wifiMgr, numOpenNetworksKept);
}
WifiConfiguration config = new WifiConfiguration();
if(SCCtlOps.isHiddenSSID)
config.hiddenSSID = true;
config.SSID = convertToQuotedString(scanResult.SSID);
if(!SCCtlOps.isHiddenSSID)
config.BSSID = scanResult.BSSID;
ConfigSec.setupSecurity_directly(config, security, password);
int id = -1;
try {
id = wifiMgr.addNetwork(config);
} catch(NullPointerException e) {
Log.e(TAG, "Weird!! Really!! What's wrong??", e);
// Weird!! Really!!
// This exception is reported by user to Android Developer Console(https://market.android.com/publish/Home)
}
if(id == -1) {
return false;
}
if(!wifiMgr.saveConfiguration()) {
return false;
}
config = getWifiConfiguration(wifiMgr, config, security);
if(config == null) {
return false;
}
return connectToConfiguredNetwork(ctx, wifiMgr, config, true);
}
/**
* Connect to a configured network.
* @param wifiManager
* @param config
* @param numOpenNetworksKept Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT
* @return
*/
public static boolean connectToConfiguredNetwork(final Context ctx, final WifiManager wifiMgr, WifiConfiguration config, boolean reassociate) {
final String security = ConfigSec.getWifiConfigurationSecurity(config);
int oldPri = config.priority;
// Make it the highest priority.
int newPri = getMaxPriority(wifiMgr) + 1;
if(newPri > MAX_PRIORITY) {
newPri = shiftPriorityAndSave(wifiMgr);
config = getWifiConfiguration(wifiMgr, config, security);
if(config == null) {
return false;
}
}
// Set highest priority to this configured network
config.priority = newPri;
int networkId = wifiMgr.updateNetwork(config);
if(networkId == -1) {
return false;
}
// Do not disable others
if(!wifiMgr.enableNetwork(networkId, false)) {
config.priority = oldPri;
return false;
}
if(!wifiMgr.saveConfiguration()) {
config.priority = oldPri;
return false;
}
// We have to retrieve the WifiConfiguration after save.
config = getWifiConfiguration(wifiMgr, config, security);
if(config == null) {
return false;
}
ReenableAllApsWhenNetworkStateChanged.schedule(ctx);
// Disable others, but do not save.
// Just to force the WifiManager to connect to it.
if(!wifiMgr.enableNetwork(config.networkId, true)) {
return false;
}
final boolean connect = reassociate ? wifiMgr.reassociate() : wifiMgr.reconnect();
if(!connect) {
return false;
}
return true;
}
private static void sortByPriority(final List<WifiConfiguration> configurations) {
java.util.Collections.sort(configurations, new Comparator<WifiConfiguration>() {
@Override
public int compare(WifiConfiguration object1,
WifiConfiguration object2) {
return object1.priority - object2.priority;
}
});
}
/**
* Ensure no more than numOpenNetworksKept open networks in configuration list.
* @param wifiMgr
* @param numOpenNetworksKept
* @return Operation succeed or not.
*/
private static boolean checkForExcessOpenNetworkAndSave(final WifiManager wifiMgr, final int numOpenNetworksKept) {
final List<WifiConfiguration> configurations = wifiMgr.getConfiguredNetworks();
sortByPriority(configurations);
boolean modified = false;
int tempCount = 0;
for(int i = configurations.size() - 1; i >= 0; i--) {
final WifiConfiguration config = configurations.get(i);
if(ConfigSec.isOpenNetwork(ConfigSec.getWifiConfigurationSecurity(config))) {
tempCount++;
if(tempCount >= numOpenNetworksKept) {
modified = true;
wifiMgr.removeNetwork(config.networkId);
}
}
}
if(modified) {
return wifiMgr.saveConfiguration();
}
return true;
}
private static final int MAX_PRIORITY = 99999;
private static int shiftPriorityAndSave(final WifiManager wifiMgr) {
final List<WifiConfiguration> configurations = wifiMgr.getConfiguredNetworks();
sortByPriority(configurations);
final int size = configurations.size();
for(int i = 0; i < size; i++) {
final WifiConfiguration config = configurations.get(i);
config.priority = i;
wifiMgr.updateNetwork(config);
}
wifiMgr.saveConfiguration();
return size;
}
private static int getMaxPriority(final WifiManager wifiManager) {
final List<WifiConfiguration> configurations = wifiManager.getConfiguredNetworks();
int pri = 0;
for(final WifiConfiguration config : configurations) {
if(config.priority > pri) {
pri = config.priority;
}
}
return pri;
}
private static final String BSSID_ANY = "any";
public static WifiConfiguration getWifiConfiguration(final WifiManager wifiMgr, final ScanResult hotsopt, String hotspotSecurity) {
final String ssid = convertToQuotedString(hotsopt.SSID);
if(ssid.length() == 0) {
return null;
}
final String bssid = hotsopt.BSSID;
if(bssid == null) {
return null;
}
if(hotspotSecurity == null) {
hotspotSecurity = ConfigSec.getScanResultSecurity(hotsopt);
}
final List<WifiConfiguration> configurations = wifiMgr.getConfiguredNetworks();
if(configurations == null) {
return null;
}
for(final WifiConfiguration config : configurations) {
if(config.SSID == null || !ssid.equals(config.SSID)) {
continue;
}
if(config.BSSID == null || BSSID_ANY.equals(config.BSSID) || bssid.equals(config.BSSID)) {
final String configSecurity = ConfigSec.getWifiConfigurationSecurity(config);
if(hotspotSecurity.equals(configSecurity)) {
return config;
}
}
}
return null;
}
public static WifiConfiguration getWifiConfiguration(final WifiManager wifiMgr, final WifiConfiguration configToFind, String security) {
final String ssid = configToFind.SSID;
if(ssid.length() == 0) {
return null;
}
final String bssid = configToFind.BSSID;
if(security == null) {
security = ConfigSec.getWifiConfigurationSecurity(configToFind);
}
final List<WifiConfiguration> configurations = wifiMgr.getConfiguredNetworks();
for(final WifiConfiguration config : configurations) {
if(config.SSID == null || !ssid.equals(config.SSID)) {
continue;
}
if(config.BSSID == null || BSSID_ANY.equals(config.BSSID) || bssid == null || bssid.equals(config.BSSID)) {
final String configSecurity = ConfigSec.getWifiConfigurationSecurity(config);
if(security.equals(configSecurity)) {
return config;
}
}
}
return null;
}
public static String convertToQuotedString(String string) {
if (TextUtils.isEmpty(string)) {
return "";
}
final int lastPos = string.length() - 1;
if(lastPos > 0 && (string.charAt(0) == '"' && string.charAt(lastPos) == '"')) {
return string;
}
return "\"" + string + "\"";
}
}

View file

@ -0,0 +1,232 @@
package com.zxing.activity;
import java.io.IOException;
import java.util.Vector;
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import com.rtk.simpleconfig_wizard.R;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.wifi.connection.MainActivity;
import com.zxing.camera.CameraManager;
import com.zxing.decoding.CaptureActivityHandler;
import com.zxing.decoding.InactivityTimer;
import com.zxing.view.ViewfinderView;
/**
* Initial the camera
* @author Ryan.Tang
*/
public class CaptureActivity extends Activity implements Callback {
private CaptureActivityHandler handler;
private ViewfinderView viewfinderView;
private boolean hasSurface;
private Vector<BarcodeFormat> decodeFormats;
private String characterSet;
private InactivityTimer inactivityTimer;
private MediaPlayer mediaPlayer;
private boolean playBeep;
private static final float BEEP_VOLUME = 0.10f;
private boolean vibrate;
private Button cancelScanButton;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.qrcode_scanner);
//ViewUtil.addTopView(getApplicationContext(), this, R.string.scan_card);
CameraManager.init(getApplication());
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
cancelScanButton = (Button) this.findViewById(R.id.btn_cancel_scan);
hasSurface = false;
inactivityTimer = new InactivityTimer(this);
}
@SuppressWarnings("deprecation")
@Override
protected void onResume() {
super.onResume();
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface) {
initCamera(surfaceHolder);
} else {
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
decodeFormats = null;
characterSet = null;
playBeep = true;
AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
playBeep = false;
}
initBeepSound();
vibrate = true;
//quit the scan view
cancelScanButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
CaptureActivity.this.finish();
}
});
}
@Override
protected void onPause() {
super.onPause();
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
CameraManager.get().closeDriver();
}
@Override
protected void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
}
/**
* Handler scan result
* @param result
* @param barcode
*/
public void handleDecode(Result result, Bitmap barcode) {
inactivityTimer.onActivity();
playBeepSoundAndVibrate();
String resultString = result.getText();
//FIXME
if (resultString.equals("")) {
Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
}else {
// System.out.println("Result:"+resultString);
Intent resultIntent = new Intent(CaptureActivity.this,MainActivity.class);
//resultIntent.putExtra("result", resultString);
//setResult(RESULT_OK, resultIntent);
Bundle bundle = new Bundle();
bundle.putString("result", resultString);
resultIntent.putExtras(bundle);
setResult(RESULT_OK, resultIntent);
}
CaptureActivity.this.finish();
}
private void initCamera(SurfaceHolder surfaceHolder) {
try {
CameraManager.get().openDriver(surfaceHolder);
} catch (IOException ioe) {
return;
} catch (RuntimeException e) {
return;
}
if (handler == null) {
handler = new CaptureActivityHandler(this, decodeFormats,
characterSet);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
public ViewfinderView getViewfinderView() {
return viewfinderView;
}
public Handler getHandler() {
return handler;
}
public void drawViewfinder() {
viewfinderView.drawViewfinder();
}
private void initBeepSound() {
if (playBeep && mediaPlayer == null) {
// The volume on STREAM_SYSTEM is not adjustable, and users found it
// too loud,
// so we now play on the music stream.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnCompletionListener(beepListener);
AssetFileDescriptor file = getResources().openRawResourceFd(
R.raw.beep);
try {
mediaPlayer.setDataSource(file.getFileDescriptor(),
file.getStartOffset(), file.getLength());
file.close();
mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
mediaPlayer.prepare();
} catch (IOException e) {
mediaPlayer = null;
}
}
}
private static final long VIBRATE_DURATION = 200L;
private void playBeepSoundAndVibrate() {
if (playBeep && mediaPlayer != null) {
mediaPlayer.start();
}
if (vibrate) {
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(VIBRATE_DURATION);
}
}
/**
* When the beep has finished playing, rewind to queue up another one.
*/
private final OnCompletionListener beepListener = new OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo(0);
}
};
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.camera;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
final class AutoFocusCallback implements Camera.AutoFocusCallback {
private static final String TAG = AutoFocusCallback.class.getSimpleName();
private static final long AUTOFOCUS_INTERVAL_MS = 1500L;
private Handler autoFocusHandler;
private int autoFocusMessage;
void setHandler(Handler autoFocusHandler, int autoFocusMessage) {
this.autoFocusHandler = autoFocusHandler;
this.autoFocusMessage = autoFocusMessage;
}
public void onAutoFocus(boolean success, Camera camera) {
if (autoFocusHandler != null) {
Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success);
autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS);
autoFocusHandler = null;
} else {
Log.d(TAG, "Got auto-focus callback, but no handler for it");
}
}
}

View file

@ -0,0 +1,267 @@
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.camera;
import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import java.util.regex.Pattern;
final class CameraConfigurationManager {
private static final String TAG = CameraConfigurationManager.class.getSimpleName();
private static final int TEN_DESIRED_ZOOM = 27;
private static final int DESIRED_SHARPNESS = 30;
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
private final Context context;
private Point screenResolution;
private Point cameraResolution;
private int previewFormat;
private String previewFormatString;
CameraConfigurationManager(Context context) {
this.context = context;
}
/**
* Reads, one time, values from the camera that are needed by the app.
*/
@SuppressWarnings("deprecation")
void initFromCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
previewFormat = parameters.getPreviewFormat();
previewFormatString = parameters.get("preview-format");
Log.d(TAG, "Default preview format: " + previewFormat + '/' + previewFormatString);
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
screenResolution = new Point(display.getWidth(), display.getHeight());
Log.d(TAG, "Screen resolution: " + screenResolution);
cameraResolution = getCameraResolution(parameters, screenResolution);
Log.d(TAG, "Camera resolution: " + screenResolution);
}
/**
* Sets the camera up to take preview images which are used for both preview and decoding.
* We detect the preview format here so that buildLuminanceSource() can build an appropriate
* LuminanceSource subclass. In the future we may want to force YUV420SP as it's the smallest,
* and the planar Y can be used for barcode scanning without a copy in some cases.
*/
void setDesiredCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
Log.d(TAG, "Setting preview size: " + cameraResolution);
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
setFlash(parameters);
setZoom(parameters);
//setSharpness(parameters);
//modify here
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
}
Point getCameraResolution() {
return cameraResolution;
}
Point getScreenResolution() {
return screenResolution;
}
int getPreviewFormat() {
return previewFormat;
}
String getPreviewFormatString() {
return previewFormatString;
}
private static Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {
String previewSizeValueString = parameters.get("preview-size-values");
// saw this on Xperia
if (previewSizeValueString == null) {
previewSizeValueString = parameters.get("preview-size-value");
}
Point cameraResolution = null;
if (previewSizeValueString != null) {
Log.d(TAG, "preview-size-values parameter: " + previewSizeValueString);
cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);
}
if (cameraResolution == null) {
// Ensure that the camera resolution is a multiple of 8, as the screen may not be.
cameraResolution = new Point(
(screenResolution.x >> 3) << 3,
(screenResolution.y >> 3) << 3);
}
return cameraResolution;
}
private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {
int bestX = 0;
int bestY = 0;
int diff = Integer.MAX_VALUE;
for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {
previewSize = previewSize.trim();
int dimPosition = previewSize.indexOf('x');
if (dimPosition < 0) {
Log.w(TAG, "Bad preview-size: " + previewSize);
continue;
}
int newX;
int newY;
try {
newX = Integer.parseInt(previewSize.substring(0, dimPosition));
newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
} catch (NumberFormatException nfe) {
Log.w(TAG, "Bad preview-size: " + previewSize);
continue;
}
int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
if (newDiff == 0) {
bestX = newX;
bestY = newY;
break;
} else if (newDiff < diff) {
bestX = newX;
bestY = newY;
diff = newDiff;
}
}
if (bestX > 0 && bestY > 0) {
return new Point(bestX, bestY);
}
return null;
}
private static int findBestMotZoomValue(CharSequence stringValues, int tenDesiredZoom) {
int tenBestValue = 0;
for (String stringValue : COMMA_PATTERN.split(stringValues)) {
stringValue = stringValue.trim();
double value;
try {
value = Double.parseDouble(stringValue);
} catch (NumberFormatException nfe) {
return tenDesiredZoom;
}
int tenValue = (int) (10.0 * value);
if (Math.abs(tenDesiredZoom - value) < Math.abs(tenDesiredZoom - tenBestValue)) {
tenBestValue = tenValue;
}
}
return tenBestValue;
}
private void setFlash(Camera.Parameters parameters) {
// FIXME: This is a hack to turn the flash off on the Samsung Galaxy.
// And this is a hack-hack to work around a different value on the Behold II
// Restrict Behold II check to Cupcake, per Samsung's advice
//if (Build.MODEL.contains("Behold II") &&
// CameraManager.SDK_INT == Build.VERSION_CODES.CUPCAKE) {
if (Build.MODEL.contains("Behold II") && CameraManager.SDK_INT == 3) { // 3 = Cupcake
parameters.set("flash-value", 1);
} else {
parameters.set("flash-value", 2);
}
// This is the standard setting to turn the flash off that all devices should honor.
parameters.set("flash-mode", "off");
}
private void setZoom(Camera.Parameters parameters) {
String zoomSupportedString = parameters.get("zoom-supported");
if (zoomSupportedString != null && !Boolean.parseBoolean(zoomSupportedString)) {
return;
}
int tenDesiredZoom = TEN_DESIRED_ZOOM;
String maxZoomString = parameters.get("max-zoom");
if (maxZoomString != null) {
try {
int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));
if (tenDesiredZoom > tenMaxZoom) {
tenDesiredZoom = tenMaxZoom;
}
} catch (NumberFormatException nfe) {
Log.w(TAG, "Bad max-zoom: " + maxZoomString);
}
}
String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
if (takingPictureZoomMaxString != null) {
try {
int tenMaxZoom = Integer.parseInt(takingPictureZoomMaxString);
if (tenDesiredZoom > tenMaxZoom) {
tenDesiredZoom = tenMaxZoom;
}
} catch (NumberFormatException nfe) {
Log.w(TAG, "Bad taking-picture-zoom-max: " + takingPictureZoomMaxString);
}
}
String motZoomValuesString = parameters.get("mot-zoom-values");
if (motZoomValuesString != null) {
tenDesiredZoom = findBestMotZoomValue(motZoomValuesString, tenDesiredZoom);
}
String motZoomStepString = parameters.get("mot-zoom-step");
if (motZoomStepString != null) {
try {
double motZoomStep = Double.parseDouble(motZoomStepString.trim());
int tenZoomStep = (int) (10.0 * motZoomStep);
if (tenZoomStep > 1) {
tenDesiredZoom -= tenDesiredZoom % tenZoomStep;
}
} catch (NumberFormatException nfe) {
// continue
}
}
// Set zoom. This helps encourage the user to pull back.
// Some devices like the Behold have a zoom parameter
if (maxZoomString != null || motZoomValuesString != null) {
parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));
}
// Most devices, like the Hero, appear to expose this zoom parameter.
// It takes on values like "27" which appears to mean 2.7x zoom
if (takingPictureZoomMaxString != null) {
parameters.set("taking-picture-zoom", tenDesiredZoom);
}
}
public static int getDesiredSharpness() {
return DESIRED_SHARPNESS;
}
}

View file

@ -0,0 +1,327 @@
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.camera;
import java.io.IOException;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.Camera;
import android.os.Build;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
/**
* This object wraps the Camera service object and expects to be the only one talking to it. The
* implementation encapsulates the steps needed to take preview-sized images, which are used for
* both preview and decoding.
*
*/
@SuppressWarnings("deprecation")
public final class CameraManager {
private static final String TAG = CameraManager.class.getSimpleName();
private static final int MIN_FRAME_WIDTH = 240;
private static final int MIN_FRAME_HEIGHT = 240;
private static final int MAX_FRAME_WIDTH = 480;
private static final int MAX_FRAME_HEIGHT = 360;
private static CameraManager cameraManager;
static final int SDK_INT; // Later we can use Build.VERSION.SDK_INT
static {
int sdkInt;
try {
sdkInt = Integer.parseInt(Build.VERSION.SDK);
} catch (NumberFormatException nfe) {
// Just to be safe
sdkInt = 10000;
}
SDK_INT = sdkInt;
}
private final Context context;
private final CameraConfigurationManager configManager;
private Camera camera;
private Rect framingRect;
private Rect framingRectInPreview;
private boolean initialized;
private boolean previewing;
private final boolean useOneShotPreviewCallback;
/**
* Preview frames are delivered here, which we pass on to the registered handler. Make sure to
* clear the handler so it will only receive one message.
*/
private final PreviewCallback previewCallback;
/** Autofocus callbacks arrive here, and are dispatched to the Handler which requested them. */
private final AutoFocusCallback autoFocusCallback;
/**
* Initializes this static object with the Context of the calling Activity.
*
* @param context The Activity which wants to use the camera.
*/
public static void init(Context context) {
if (cameraManager == null) {
cameraManager = new CameraManager(context);
}
}
/**
* Gets the CameraManager singleton instance.
*
* @return A reference to the CameraManager singleton.
*/
public static CameraManager get() {
return cameraManager;
}
private CameraManager(Context context) {
this.context = context;
this.configManager = new CameraConfigurationManager(context);
// Camera.setOneShotPreviewCallback() has a race condition in Cupcake, so we use the older
// Camera.setPreviewCallback() on 1.5 and earlier. For Donut and later, we need to use
// the more efficient one shot callback, as the older one can swamp the system and cause it
// to run out of memory. We can't use SDK_INT because it was introduced in the Donut SDK.
//useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > Build.VERSION_CODES.CUPCAKE;
useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > 3; // 3 = Cupcake
previewCallback = new PreviewCallback(configManager, useOneShotPreviewCallback);
autoFocusCallback = new AutoFocusCallback();
}
/**
* Opens the camera driver and initializes the hardware parameters.
*
* @param holder The surface object which the camera will draw preview frames into.
* @throws IOException Indicates the camera driver failed to open.
*/
public void openDriver(SurfaceHolder holder) throws IOException {
if (camera == null) {
camera = Camera.open();
if (camera == null) {
throw new IOException();
}
camera.setPreviewDisplay(holder);
if (!initialized) {
initialized = true;
configManager.initFromCameraParameters(camera);
}
configManager.setDesiredCameraParameters(camera);
//FIXME
// SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
//ÊÇ·ñʹÓÃǰµÆ
// if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {
// FlashlightManager.enableFlashlight();
// }
FlashlightManager.enableFlashlight();
}
}
/**
* Closes the camera driver if still in use.
*/
public void closeDriver() {
if (camera != null) {
FlashlightManager.disableFlashlight();
camera.release();
camera = null;
}
}
/**
* Asks the camera hardware to begin drawing preview frames to the screen.
*/
public void startPreview() {
if (camera != null && !previewing) {
camera.startPreview();
previewing = true;
}
}
/**
* Tells the camera to stop drawing preview frames.
*/
public void stopPreview() {
if (camera != null && previewing) {
if (!useOneShotPreviewCallback) {
camera.setPreviewCallback(null);
}
camera.stopPreview();
previewCallback.setHandler(null, 0);
autoFocusCallback.setHandler(null, 0);
previewing = false;
}
}
/**
* A single preview frame will be returned to the handler supplied. The data will arrive as byte[]
* in the message.obj field, with width and height encoded as message.arg1 and message.arg2,
* respectively.
*
* @param handler The handler to send the message to.
* @param message The what field of the message to be sent.
*/
public void requestPreviewFrame(Handler handler, int message) {
if (camera != null && previewing) {
previewCallback.setHandler(handler, message);
if (useOneShotPreviewCallback) {
camera.setOneShotPreviewCallback(previewCallback);
} else {
camera.setPreviewCallback(previewCallback);
}
}
}
/**
* Asks the camera hardware to perform an autofocus.
*
* @param handler The Handler to notify when the autofocus completes.
* @param message The message to deliver.
*/
public void requestAutoFocus(Handler handler, int message) {
if (camera != null && previewing) {
autoFocusCallback.setHandler(handler, message);
//Log.d(TAG, "Requesting auto-focus callback");
camera.autoFocus(autoFocusCallback);
}
}
/**
* Calculates the framing rect which the UI should draw to show the user where to place the
* barcode. This target helps with alignment as well as forces the user to hold the device
* far enough away to ensure the image will be in focus.
*
* @return The rectangle to draw on screen in window coordinates.
*/
public Rect getFramingRect() {
Point screenResolution = configManager.getScreenResolution();
if (framingRect == null) {
if (camera == null) {
return null;
}
int width = screenResolution.x * 3 / 4;
if (width < MIN_FRAME_WIDTH) {
width = MIN_FRAME_WIDTH;
} else if (width > MAX_FRAME_WIDTH) {
width = MAX_FRAME_WIDTH;
}
int height = screenResolution.y * 3 / 4;
if (height < MIN_FRAME_HEIGHT) {
height = MIN_FRAME_HEIGHT;
} else if (height > MAX_FRAME_HEIGHT) {
height = MAX_FRAME_HEIGHT;
}
int leftOffset = (screenResolution.x - width) / 2;
int topOffset = (screenResolution.y - height) / 2;
framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
Log.d(TAG, "Calculated framing rect: " + framingRect);
}
return framingRect;
}
/**
* Like {@link #getFramingRect} but coordinates are in terms of the preview frame,
* not UI / screen.
*/
public Rect getFramingRectInPreview() {
if (framingRectInPreview == null) {
Rect rect = new Rect(getFramingRect());
Point cameraResolution = configManager.getCameraResolution();
Point screenResolution = configManager.getScreenResolution();
//modify here
// rect.left = rect.left * cameraResolution.x / screenResolution.x;
// rect.right = rect.right * cameraResolution.x / screenResolution.x;
// rect.top = rect.top * cameraResolution.y / screenResolution.y;
// rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
rect.left = rect.left * cameraResolution.y / screenResolution.x;
rect.right = rect.right * cameraResolution.y / screenResolution.x;
rect.top = rect.top * cameraResolution.x / screenResolution.y;
rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
framingRectInPreview = rect;
}
return framingRectInPreview;
}
/**
* Converts the result points from still resolution coordinates to screen coordinates.
*
* @param points The points returned by the Reader subclass through Result.getResultPoints().
* @return An array of Points scaled to the size of the framing rect and offset appropriately
* so they can be drawn in screen coordinates.
*/
/*
public Point[] convertResultPoints(ResultPoint[] points) {
Rect frame = getFramingRectInPreview();
int count = points.length;
Point[] output = new Point[count];
for (int x = 0; x < count; x++) {
output[x] = new Point();
output[x].x = frame.left + (int) (points[x].getX() + 0.5f);
output[x].y = frame.top + (int) (points[x].getY() + 0.5f);
}
return output;
}
*/
/**
* A factory method to build the appropriate LuminanceSource object based on the format
* of the preview buffers, as described by Camera.Parameters.
*
* @param data A preview frame.
* @param width The width of the image.
* @param height The height of the image.
* @return A PlanarYUVLuminanceSource instance.
*/
public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
Rect rect = getFramingRectInPreview();
int previewFormat = configManager.getPreviewFormat();
String previewFormatString = configManager.getPreviewFormatString();
switch (previewFormat) {
// This is the standard Android format which all devices are REQUIRED to support.
// In theory, it's the only one we should ever care about.
case PixelFormat.YCbCr_420_SP:
// This format has never been seen in the wild, but is compatible as we only care
// about the Y channel, so allow it.
case PixelFormat.YCbCr_422_SP:
return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
rect.width(), rect.height());
default:
// The Samsung Moment incorrectly uses this variant instead of the 'sp' version.
// Fortunately, it too has all the Y data up front, so we can read it.
if ("yuv420p".equals(previewFormatString)) {
return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
rect.width(), rect.height());
}
}
throw new IllegalArgumentException("Unsupported picture format: " +
previewFormat + '/' + previewFormatString);
}
public Context getContext() {
return context;
}
}

View file

@ -0,0 +1,150 @@
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.camera;
import android.os.IBinder;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* This class is used to activate the weak light on some camera phones (not flash)
* in order to illuminate surfaces for scanning. There is no official way to do this,
* but, classes which allow access to this function still exist on some devices.
* This therefore proceeds through a great deal of reflection.
*
* See <a href="http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/">
* http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/</a> and
* <a href="http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java">
* http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java</a>.
* Thanks to Ryan Alford for pointing out the availability of this class.
*/
final class FlashlightManager {
private static final String TAG = FlashlightManager.class.getSimpleName();
private static final Object iHardwareService;
private static final Method setFlashEnabledMethod;
static {
iHardwareService = getHardwareService();
setFlashEnabledMethod = getSetFlashEnabledMethod(iHardwareService);
if (iHardwareService == null) {
Log.v(TAG, "This device does supports control of a flashlight");
} else {
Log.v(TAG, "This device does not support control of a flashlight");
}
}
private FlashlightManager() {
}
/**
* ¿ØÖÆÏà»úÉÁ¹âµÆ¿ª¹Ø
*/
//FIXME
static void enableFlashlight() {
setFlashlight(false);
}
static void disableFlashlight() {
setFlashlight(false);
}
private static Object getHardwareService() {
Class<?> serviceManagerClass = maybeForName("android.os.ServiceManager");
if (serviceManagerClass == null) {
return null;
}
Method getServiceMethod = maybeGetMethod(serviceManagerClass, "getService", String.class);
if (getServiceMethod == null) {
return null;
}
Object hardwareService = invoke(getServiceMethod, null, "hardware");
if (hardwareService == null) {
return null;
}
Class<?> iHardwareServiceStubClass = maybeForName("android.os.IHardwareService$Stub");
if (iHardwareServiceStubClass == null) {
return null;
}
Method asInterfaceMethod = maybeGetMethod(iHardwareServiceStubClass, "asInterface", IBinder.class);
if (asInterfaceMethod == null) {
return null;
}
return invoke(asInterfaceMethod, null, hardwareService);
}
private static Method getSetFlashEnabledMethod(Object iHardwareService) {
if (iHardwareService == null) {
return null;
}
Class<?> proxyClass = iHardwareService.getClass();
return maybeGetMethod(proxyClass, "setFlashlightEnabled", boolean.class);
}
private static Class<?> maybeForName(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException cnfe) {
// OK
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while finding class " + name, re);
return null;
}
}
private static Method maybeGetMethod(Class<?> clazz, String name, Class<?>... argClasses) {
try {
return clazz.getMethod(name, argClasses);
} catch (NoSuchMethodException nsme) {
// OK
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while finding method " + name, re);
return null;
}
}
private static Object invoke(Method method, Object instance, Object... args) {
try {
return method.invoke(instance, args);
} catch (IllegalAccessException e) {
Log.w(TAG, "Unexpected error while invoking " + method, e);
return null;
} catch (InvocationTargetException e) {
Log.w(TAG, "Unexpected error while invoking " + method, e.getCause());
return null;
} catch (RuntimeException re) {
Log.w(TAG, "Unexpected error while invoking " + method, re);
return null;
}
}
private static void setFlashlight(boolean active) {
if (iHardwareService != null) {
invoke(setFlashEnabledMethod, iHardwareService, active);
}
}
}

View file

@ -0,0 +1,133 @@
/*
* Copyright 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.camera;
import com.google.zxing.LuminanceSource;
import android.graphics.Bitmap;
/**
* This object extends LuminanceSource around an array of YUV data returned from the camera driver,
* with the option to crop to a rectangle within the full data. This can be used to exclude
* superfluous pixels around the perimeter and speed up decoding.
*
* It works for any pixel format where the Y channel is planar and appears first, including
* YCbCr_420_SP and YCbCr_422_SP.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public final class PlanarYUVLuminanceSource extends LuminanceSource {
private final byte[] yuvData;
private final int dataWidth;
private final int dataHeight;
private final int left;
private final int top;
public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top,
int width, int height) {
super(width, height);
if (left + width > dataWidth || top + height > dataHeight) {
throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
}
this.yuvData = yuvData;
this.dataWidth = dataWidth;
this.dataHeight = dataHeight;
this.left = left;
this.top = top;
}
@Override
public byte[] getRow(int y, byte[] row) {
if (y < 0 || y >= getHeight()) {
throw new IllegalArgumentException("Requested row is outside the image: " + y);
}
int width = getWidth();
if (row == null || row.length < width) {
row = new byte[width];
}
int offset = (y + top) * dataWidth + left;
System.arraycopy(yuvData, offset, row, 0, width);
return row;
}
@Override
public byte[] getMatrix() {
int width = getWidth();
int height = getHeight();
// If the caller asks for the entire underlying image, save the copy and give them the
// original data. The docs specifically warn that result.length must be ignored.
if (width == dataWidth && height == dataHeight) {
return yuvData;
}
int area = width * height;
byte[] matrix = new byte[area];
int inputOffset = top * dataWidth + left;
// If the width matches the full width of the underlying data, perform a single copy.
if (width == dataWidth) {
System.arraycopy(yuvData, inputOffset, matrix, 0, area);
return matrix;
}
// Otherwise copy one cropped row at a time.
byte[] yuv = yuvData;
for (int y = 0; y < height; y++) {
int outputOffset = y * width;
System.arraycopy(yuv, inputOffset, matrix, outputOffset, width);
inputOffset += dataWidth;
}
return matrix;
}
@Override
public boolean isCropSupported() {
return true;
}
public int getDataWidth() {
return dataWidth;
}
public int getDataHeight() {
return dataHeight;
}
public Bitmap renderCroppedGreyscaleBitmap() {
int width = getWidth();
int height = getHeight();
int[] pixels = new int[width * height];
byte[] yuv = yuvData;
int inputOffset = top * dataWidth + left;
for (int y = 0; y < height; y++) {
int outputOffset = y * width;
for (int x = 0; x < width; x++) {
int grey = yuv[inputOffset + x] & 0xff;
pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);
}
inputOffset += dataWidth;
}
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.camera;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
final class PreviewCallback implements Camera.PreviewCallback {
private static final String TAG = PreviewCallback.class.getSimpleName();
private final CameraConfigurationManager configManager;
private final boolean useOneShotPreviewCallback;
private Handler previewHandler;
private int previewMessage;
PreviewCallback(CameraConfigurationManager configManager, boolean useOneShotPreviewCallback) {
this.configManager = configManager;
this.useOneShotPreviewCallback = useOneShotPreviewCallback;
}
void setHandler(Handler previewHandler, int previewMessage) {
this.previewHandler = previewHandler;
this.previewMessage = previewMessage;
}
public void onPreviewFrame(byte[] data, Camera camera) {
Point cameraResolution = configManager.getCameraResolution();
if (!useOneShotPreviewCallback) {
camera.setPreviewCallback(null);
}
if (previewHandler != null) {
Message message = previewHandler.obtainMessage(previewMessage, cameraResolution.x,
cameraResolution.y, data);
message.sendToTarget();
previewHandler = null;
} else {
Log.d(TAG, "Got preview callback, but no handler for it");
}
}
}

View file

@ -0,0 +1,137 @@
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.decoding;
import java.util.Vector;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.rtk.simpleconfig_wizard.R;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.zxing.activity.CaptureActivity;
import com.zxing.camera.CameraManager;
import com.zxing.view.ViewfinderResultPointCallback;
/**
* This class handles all the messaging which comprises the state machine for capture.
*/
public final class CaptureActivityHandler extends Handler {
private static final String TAG = CaptureActivityHandler.class.getSimpleName();
private final CaptureActivity activity;
private final DecodeThread decodeThread;
private State state;
private enum State {
PREVIEW,
SUCCESS,
DONE
}
public CaptureActivityHandler(CaptureActivity activity, Vector<BarcodeFormat> decodeFormats,
String characterSet) {
this.activity = activity;
decodeThread = new DecodeThread(activity, decodeFormats, characterSet,
new ViewfinderResultPointCallback(activity.getViewfinderView()));
decodeThread.start();
state = State.SUCCESS;
// Start ourselves capturing previews and decoding.
CameraManager.get().startPreview();
restartPreviewAndDecode();
}
@Override
public void handleMessage(Message message) {
switch (message.what) {
case R.id.auto_focus:
//Log.d(TAG, "Got auto-focus message");
// When one auto focus pass finishes, start another. This is the closest thing to
// continuous AF. It does seem to hunt a bit, but I'm not sure what else to do.
if (state == State.PREVIEW) {
CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
}
break;
case R.id.restart_preview:
Log.d(TAG, "Got restart preview message");
restartPreviewAndDecode();
break;
case R.id.decode_succeeded:
Log.d(TAG, "Got decode succeeded message");
state = State.SUCCESS;
Bundle bundle = message.getData();
/***********************************************************************/
Bitmap barcode = bundle == null ? null :
(Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP);
activity.handleDecode((Result) message.obj, barcode);/***********************************************************************/
break;
case R.id.decode_failed:
// We're decoding as fast as possible, so when one decode fails, start another.
state = State.PREVIEW;
CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
break;
case R.id.return_scan_result:
Log.d(TAG, "Got return scan result message");
activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
activity.finish();
break;
case R.id.launch_product_query:
Log.d(TAG, "Got product query message");
String url = (String) message.obj;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
activity.startActivity(intent);
break;
}
}
public void quitSynchronously() {
state = State.DONE;
CameraManager.get().stopPreview();
Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit);
quit.sendToTarget();
try {
decodeThread.join();
} catch (InterruptedException e) {
// continue
}
// Be absolutely sure we don't send any queued up messages
removeMessages(R.id.decode_succeeded);
removeMessages(R.id.decode_failed);
}
private void restartPreviewAndDecode() {
if (state == State.SUCCESS) {
state = State.PREVIEW;
CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
activity.drawViewfinder();
}
}
}

View file

@ -0,0 +1,104 @@
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.decoding;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import java.util.regex.Pattern;
import android.content.Intent;
import android.net.Uri;
import com.google.zxing.BarcodeFormat;
final class DecodeFormatManager {
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
static final Vector<BarcodeFormat> PRODUCT_FORMATS;
static final Vector<BarcodeFormat> ONE_D_FORMATS;
static final Vector<BarcodeFormat> QR_CODE_FORMATS;
static final Vector<BarcodeFormat> DATA_MATRIX_FORMATS;
static {
PRODUCT_FORMATS = new Vector<BarcodeFormat>(5);
PRODUCT_FORMATS.add(BarcodeFormat.UPC_A);
PRODUCT_FORMATS.add(BarcodeFormat.UPC_E);
PRODUCT_FORMATS.add(BarcodeFormat.EAN_13);
PRODUCT_FORMATS.add(BarcodeFormat.EAN_8);
PRODUCT_FORMATS.add(BarcodeFormat.RSS14);
ONE_D_FORMATS = new Vector<BarcodeFormat>(PRODUCT_FORMATS.size() + 4);
ONE_D_FORMATS.addAll(PRODUCT_FORMATS);
ONE_D_FORMATS.add(BarcodeFormat.CODE_39);
ONE_D_FORMATS.add(BarcodeFormat.CODE_93);
ONE_D_FORMATS.add(BarcodeFormat.CODE_128);
ONE_D_FORMATS.add(BarcodeFormat.ITF);
QR_CODE_FORMATS = new Vector<BarcodeFormat>(1);
QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE);
DATA_MATRIX_FORMATS = new Vector<BarcodeFormat>(1);
DATA_MATRIX_FORMATS.add(BarcodeFormat.DATA_MATRIX);
}
private DecodeFormatManager() {}
static Vector<BarcodeFormat> parseDecodeFormats(Intent intent) {
List<String> scanFormats = null;
String scanFormatsString = intent.getStringExtra(Intents.Scan.SCAN_FORMATS);
if (scanFormatsString != null) {
scanFormats = Arrays.asList(COMMA_PATTERN.split(scanFormatsString));
}
return parseDecodeFormats(scanFormats, intent.getStringExtra(Intents.Scan.MODE));
}
static Vector<BarcodeFormat> parseDecodeFormats(Uri inputUri) {
List<String> formats = inputUri.getQueryParameters(Intents.Scan.SCAN_FORMATS);
if (formats != null && formats.size() == 1 && formats.get(0) != null){
formats = Arrays.asList(COMMA_PATTERN.split(formats.get(0)));
}
return parseDecodeFormats(formats, inputUri.getQueryParameter(Intents.Scan.MODE));
}
private static Vector<BarcodeFormat> parseDecodeFormats(Iterable<String> scanFormats,
String decodeMode) {
if (scanFormats != null) {
Vector<BarcodeFormat> formats = new Vector<BarcodeFormat>();
try {
for (String format : scanFormats) {
formats.add(BarcodeFormat.valueOf(format));
}
return formats;
} catch (IllegalArgumentException iae) {
// ignore it then
}
}
if (decodeMode != null) {
if (Intents.Scan.PRODUCT_MODE.equals(decodeMode)) {
return PRODUCT_FORMATS;
}
if (Intents.Scan.QR_CODE_MODE.equals(decodeMode)) {
return QR_CODE_FORMATS;
}
if (Intents.Scan.DATA_MATRIX_MODE.equals(decodeMode)) {
return DATA_MATRIX_FORMATS;
}
if (Intents.Scan.ONE_D_MODE.equals(decodeMode)) {
return ONE_D_FORMATS;
}
}
return null;
}
}

View file

@ -0,0 +1,110 @@
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.decoding;
import java.util.Hashtable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
//import android.util.Log;
import com.rtk.simpleconfig_wizard.R;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.zxing.activity.CaptureActivity;
import com.zxing.camera.CameraManager;
import com.zxing.camera.PlanarYUVLuminanceSource;
final class DecodeHandler extends Handler {
// private static final String TAG = DecodeHandler.class.getSimpleName();
private final CaptureActivity activity;
private final MultiFormatReader multiFormatReader;
DecodeHandler(CaptureActivity activity, Hashtable<DecodeHintType, Object> hints) {
multiFormatReader = new MultiFormatReader();
multiFormatReader.setHints(hints);
this.activity = activity;
}
@Override
public void handleMessage(Message message) {
switch (message.what) {
case R.id.decode:
//Log.d(TAG, "Got decode message");
decode((byte[]) message.obj, message.arg1, message.arg2);
break;
case R.id.quit:
Looper.myLooper().quit();
break;
}
}
/**
* Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,
* reuse the same reader objects from one decode to the next.
*
* @param data The YUV preview frame.
* @param width The width of the preview frame.
* @param height The height of the preview frame.
*/
private void decode(byte[] data, int width, int height) {
// long start = System.currentTimeMillis();
Result rawResult = null;
//modify here
byte[] rotatedData = new byte[data.length];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
rotatedData[x * height + height - y - 1] = data[x + y * width];
}
int tmp = width; // Here we are swapping, that's the difference to #11
width = height;
height = tmp;
PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(rotatedData, width, height);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
rawResult = multiFormatReader.decodeWithState(bitmap);
} catch (ReaderException re) {
// continue
} finally {
multiFormatReader.reset();
}
if (rawResult != null) {
// long end = System.currentTimeMillis();
// Log.d(TAG, "Found barcode (" + (end - start) + " ms):\n" + rawResult.toString());
Message message = Message.obtain(activity.getHandler(), R.id.decode_succeeded, rawResult);
Bundle bundle = new Bundle();
bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
message.setData(bundle);
//Log.d(TAG, "Sending decode succeeded message...");
message.sendToTarget();
} else {
Message message = Message.obtain(activity.getHandler(), R.id.decode_failed);
message.sendToTarget();
}
}
}

View file

@ -0,0 +1,86 @@
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.decoding;
import java.util.Hashtable;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import android.os.Handler;
import android.os.Looper;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.ResultPointCallback;
import com.zxing.activity.CaptureActivity;
/**
* This thread does all the heavy lifting of decoding the images.
* ½âÂëÏß³Ì
*/
final class DecodeThread extends Thread {
public static final String BARCODE_BITMAP = "barcode_bitmap";
private final CaptureActivity activity;
private final Hashtable<DecodeHintType, Object> hints;
private Handler handler;
private final CountDownLatch handlerInitLatch;
DecodeThread(CaptureActivity activity,
Vector<BarcodeFormat> decodeFormats,
String characterSet,
ResultPointCallback resultPointCallback) {
this.activity = activity;
handlerInitLatch = new CountDownLatch(1);
hints = new Hashtable<DecodeHintType, Object>(3);
if (decodeFormats == null || decodeFormats.isEmpty()) {
decodeFormats = new Vector<BarcodeFormat>();
decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
}
hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
if (characterSet != null) {
hints.put(DecodeHintType.CHARACTER_SET, characterSet);
}
hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback);
}
Handler getHandler() {
try {
handlerInitLatch.await();
} catch (InterruptedException ie) {
// continue?
}
return handler;
}
@Override
public void run() {
Looper.prepare();
handler = new DecodeHandler(activity, hints);
handlerInitLatch.countDown();
Looper.loop();
}
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.decoding;
import android.app.Activity;
import android.content.DialogInterface;
/**
* Simple listener used to exit the app in a few cases.
*
*/
public final class FinishListener
implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, Runnable {
private final Activity activityToFinish;
public FinishListener(Activity activityToFinish) {
this.activityToFinish = activityToFinish;
}
public void onCancel(DialogInterface dialogInterface) {
run();
}
public void onClick(DialogInterface dialogInterface, int i) {
run();
}
public void run() {
activityToFinish.finish();
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 2010 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.decoding;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
/**
* Finishes an activity after a period of inactivity.
*/
public final class InactivityTimer {
private static final int INACTIVITY_DELAY_SECONDS = 5 * 60;
private final ScheduledExecutorService inactivityTimer =
Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
private final Activity activity;
private ScheduledFuture<?> inactivityFuture = null;
public InactivityTimer(Activity activity) {
this.activity = activity;
onActivity();
}
public void onActivity() {
cancel();
inactivityFuture = inactivityTimer.schedule(new FinishListener(activity),
INACTIVITY_DELAY_SECONDS,
TimeUnit.SECONDS);
}
private void cancel() {
if (inactivityFuture != null) {
inactivityFuture.cancel(true);
inactivityFuture = null;
}
}
public void shutdown() {
cancel();
inactivityTimer.shutdown();
}
private static final class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable);
thread.setDaemon(true);
return thread;
}
}
}

View file

@ -0,0 +1,190 @@
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.decoding;
/**
* This class provides the constants to use when sending an Intent to Barcode Scanner.
* These strings are effectively API and cannot be changed.
*/
public final class Intents {
private Intents() {
}
public static final class Scan {
/**
* Send this intent to open the Barcodes app in scanning mode, find a barcode, and return
* the results.
*/
public static final String ACTION = "com.google.zxing.client.android.SCAN";
/**
* By default, sending Scan.ACTION will decode all barcodes that we understand. However it
* may be useful to limit scanning to certain formats. Use Intent.putExtra(MODE, value) with
* one of the values below ({@link #PRODUCT_MODE}, {@link #ONE_D_MODE}, {@link #QR_CODE_MODE}).
* Optional.
*
* Setting this is effectively shorthnad for setting explicit formats with {@link #SCAN_FORMATS}.
* It is overridden by that setting.
*/
public static final String MODE = "SCAN_MODE";
/**
* Comma-separated list of formats to scan for. The values must match the names of
* {@link com.google.zxing.BarcodeFormat}s, such as {@link com.google.zxing.BarcodeFormat#EAN_13}.
* Example: "EAN_13,EAN_8,QR_CODE"
*
* This overrides {@link #MODE}.
*/
public static final String SCAN_FORMATS = "SCAN_FORMATS";
/**
* @see com.google.zxing.DecodeHintType#CHARACTER_SET
*/
public static final String CHARACTER_SET = "CHARACTER_SET";
/**
* Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get
* prices, reviews, etc. for products.
*/
public static final String PRODUCT_MODE = "PRODUCT_MODE";
/**
* Decode only 1D barcodes (currently UPC, EAN, Code 39, and Code 128).
*/
public static final String ONE_D_MODE = "ONE_D_MODE";
/**
* Decode only QR codes.
*/
public static final String QR_CODE_MODE = "QR_CODE_MODE";
/**
* Decode only Data Matrix codes.
*/
public static final String DATA_MATRIX_MODE = "DATA_MATRIX_MODE";
/**
* If a barcode is found, Barcodes returns RESULT_OK to onActivityResult() of the app which
* requested the scan via startSubActivity(). The barcodes contents can be retrieved with
* intent.getStringExtra(RESULT). If the user presses Back, the result code will be
* RESULT_CANCELED.
*/
public static final String RESULT = "SCAN_RESULT";
/**
* Call intent.getStringExtra(RESULT_FORMAT) to determine which barcode format was found.
* See Contents.Format for possible values.
*/
public static final String RESULT_FORMAT = "SCAN_RESULT_FORMAT";
/**
* Setting this to false will not save scanned codes in the history.
*/
public static final String SAVE_HISTORY = "SAVE_HISTORY";
private Scan() {
}
}
public static final class Encode {
/**
* Send this intent to encode a piece of data as a QR code and display it full screen, so
* that another person can scan the barcode from your screen.
*/
public static final String ACTION = "com.google.zxing.client.android.ENCODE";
/**
* The data to encode. Use Intent.putExtra(DATA, data) where data is either a String or a
* Bundle, depending on the type and format specified. Non-QR Code formats should
* just use a String here. For QR Code, see Contents for details.
*/
public static final String DATA = "ENCODE_DATA";
/**
* The type of data being supplied if the format is QR Code. Use
* Intent.putExtra(TYPE, type) with one of Contents.Type.
*/
public static final String TYPE = "ENCODE_TYPE";
/**
* The barcode format to be displayed. If this isn't specified or is blank,
* it defaults to QR Code. Use Intent.putExtra(FORMAT, format), where
* format is one of Contents.Format.
*/
public static final String FORMAT = "ENCODE_FORMAT";
private Encode() {
}
}
public static final class SearchBookContents {
/**
* Use Google Book Search to search the contents of the book provided.
*/
public static final String ACTION = "com.google.zxing.client.android.SEARCH_BOOK_CONTENTS";
/**
* The book to search, identified by ISBN number.
*/
public static final String ISBN = "ISBN";
/**
* An optional field which is the text to search for.
*/
public static final String QUERY = "QUERY";
private SearchBookContents() {
}
}
public static final class WifiConnect {
/**
* Internal intent used to trigger connection to a wi-fi network.
*/
public static final String ACTION = "com.google.zxing.client.android.WIFI_CONNECT";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String SSID = "SSID";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String TYPE = "TYPE";
/**
* The network to connect to, all the configuration provided here.
*/
public static final String PASSWORD = "PASSWORD";
private WifiConnect() {
}
}
public static final class Share {
/**
* Give the user a choice of items to encode as a barcode, then render it as a QR Code and
* display onscreen for a friend to scan with their phone.
*/
public static final String ACTION = "com.google.zxing.client.android.SHARE";
private Share() {
}
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.view;
import com.google.zxing.ResultPoint;
import com.google.zxing.ResultPointCallback;
public final class ViewfinderResultPointCallback implements ResultPointCallback {
private final ViewfinderView viewfinderView;
public ViewfinderResultPointCallback(ViewfinderView viewfinderView) {
this.viewfinderView = viewfinderView;
}
public void foundPossibleResultPoint(ResultPoint point) {
viewfinderView.addPossibleResultPoint(point);
}
}

View file

@ -0,0 +1,154 @@
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zxing.view;
import java.util.Collection;
import java.util.HashSet;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import com.rtk.simpleconfig_wizard.R;
import com.google.zxing.ResultPoint;
import com.zxing.camera.CameraManager;
/**
* This view is overlaid on top of the camera preview. It adds the viewfinder rectangle and partial
* transparency outside it, as well as the laser scanner animation and result points.
*/
public final class ViewfinderView extends View {
private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
private static final long ANIMATION_DELAY = 100L;
private static final int OPAQUE = 0xFF;
private final Paint paint;
private Bitmap resultBitmap;
private final int maskColor;
private final int resultColor;
private final int frameColor;
private final int laserColor;
private final int resultPointColor;
private int scannerAlpha;
private Collection<ResultPoint> possibleResultPoints;
private Collection<ResultPoint> lastPossibleResultPoints;
// This constructor is used when the class is built from an XML resource.
public ViewfinderView(Context context, AttributeSet attrs) {
super(context, attrs);
// Initialize these once for performance rather than calling them every time in onDraw().
paint = new Paint();
Resources resources = getResources();
maskColor = resources.getColor(R.color.viewfinder_mask);
resultColor = resources.getColor(R.color.result_view);
frameColor = resources.getColor(R.color.viewfinder_frame);
laserColor = resources.getColor(R.color.viewfinder_laser);
resultPointColor = resources.getColor(R.color.possible_result_points);
scannerAlpha = 0;
possibleResultPoints = new HashSet<ResultPoint>(5);
}
@Override
public void onDraw(Canvas canvas) {
Rect frame = CameraManager.get().getFramingRect();
if (frame == null) {
return;
}
int width = canvas.getWidth();
int height = canvas.getHeight();
// Draw the exterior (i.e. outside the framing rect) darkened
paint.setColor(resultBitmap != null ? resultColor : maskColor);
canvas.drawRect(0, 0, width, frame.top, paint);
canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
canvas.drawRect(0, frame.bottom + 1, width, height, paint);
if (resultBitmap != null) {
// Draw the opaque result bitmap over the scanning rectangle
paint.setAlpha(OPAQUE);
canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);
} else {
// Draw a two pixel solid black border inside the framing rect
paint.setColor(frameColor);
canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint);
canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint);
canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint);
canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint);
// Draw a red "laser scanner" line through the middle to show decoding is active
paint.setColor(laserColor);
paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
int middle = frame.height() / 2 + frame.top;
canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
Collection<ResultPoint> currentPossible = possibleResultPoints;
Collection<ResultPoint> currentLast = lastPossibleResultPoints;
if (currentPossible.isEmpty()) {
lastPossibleResultPoints = null;
} else {
possibleResultPoints = new HashSet<ResultPoint>(5);
lastPossibleResultPoints = currentPossible;
paint.setAlpha(OPAQUE);
paint.setColor(resultPointColor);
for (ResultPoint point : currentPossible) {
canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint);
}
}
if (currentLast != null) {
paint.setAlpha(OPAQUE / 2);
paint.setColor(resultPointColor);
for (ResultPoint point : currentLast) {
canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 3.0f, paint);
}
}
// Request another update at the animation interval, but only repaint the laser line,
// not the entire viewfinder mask.
postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom);
}
}
public void drawViewfinder() {
resultBitmap = null;
invalidate();
}
/**
* Draw a bitmap with the result points highlighted instead of the live scanning display.
*
* @param barcode An image of the decoded barcode.
*/
public void drawResultBitmap(Bitmap barcode) {
resultBitmap = barcode;
invalidate();
}
public void addPossibleResultPoint(ResultPoint point) {
possibleResultPoints.add(point);
}
}