工程项目CPU白卡写入数据信息。

来源:互联网 发布:excel数据透视表命名 编辑:程序博客网 时间:2024/05/16 19:12

项目:

1.安装Apk文件,手持机目录下创建 PSAM_Demo文件夹。  代码 MyApplication类。
2.把需要写入到CPU卡的信息文件存放到手持机 PSAM_Demo文件夹下。
3.打开应用页面1(标题Write),把CPU卡放在手持机背部。
    写入步骤:
    1.CPU卡上电。
    2.COS指令:选择  删除MF(对CPU卡进行信息擦出)    点击sendCMD,发送删除MF命令。
    3.COS指令:选择  1.建立EF2001     点击sendCMD   09C4=2500字节(创建的EF文件空间大小)
    4.COS指令:      选择2001         点击sendCMD
    5.写出本地文件名:输入PSAM_Demo文件夹下,需要写入到CPU卡的文件名和后缀
    6.点击cpuWrite: 返回数据 9000,直到返回数据显示 write over! 说明写出完成。
注意:写入信息为CPU卡二进制文件。如需写入多个文件,则需要建立多个EF文件(需自定义空间大小),写入时,需选择该文件,才能进行写入操作。
写入规则:
    【一】.【文件长度不足200,直接写入。 内容为:前3个长度标记的是文件长度。后面是文件信息内容。
   列:欲向卡中写入1122334455667788数据。在读取时,又能知道该文件需读08个长度的数据。
       如11占2个字符=1字节。
       数据长度16字符=8字节。要求数据长度2字节    (数据长度=08)
       前3字节为数据长度,不足3字节,用C补足      (3字节数据长度=08CCCC)
       写入数据总长度:3+8=11,转16字节为B, 要求2字节=0B.(写入数据=08CCCC1122334455667788)
       命令:
       00D600000B08CCCC1122334455667788
      命令解析:00D600000B08CCCC1122334455667788 
      EF目录下写二进制文件:00()D6()00(p1)00(p2)0B(写入信息总长度为11,转16进制=0B)08CCCC1122334455667788(写入的11位数据) 返回码: 9000标示写入成功。   
    【二】.【文件长度大于200,分次循环写入。 内容为:前3个长度标记的是文件长度。后面是文件信息内容。首次写入3字节,后依次写入200字节和剩余不足200字节的数据。依次写入时,再次写入位置从上次末尾位置开始,所以要计算写的偏移量,首次从0开始写入3字节,第二次偏移量为偏移 3+(200*N次)(N从0开始)】



【一. activity_ucpu_split_write.xml  布局】

<?xml version="1.0" encoding="UTF-8"?>
<!-- SAM卡 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/psam_card"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="30dp"
        android:orientation="vertical" >


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal" >


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/cos_cmd" />


            <Spinner
                android:id="@+id/cpu_cos_cmd"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout> 
         <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal" >


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="写出本地文件名称:" />


            <EditText
                android:id="@+id/path"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:singleLine="true" />
        </LinearLayout>
         <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal" >


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/send_data" />


            <EditText
                android:id="@+id/cpu_send_data"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:singleLine="true" />
        </LinearLayout>
        
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal" >


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/receive_data" />


            <EditText
                android:id="@+id/cpu_receive_data"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="12sp"
                />
        </LinearLayout>


    </LinearLayout>


    <TableLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
         >


        <TableRow
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" >


            <Button
                android:id="@+id/cpu_reset"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
               
                android:text="cpu上电" />
      
        </TableRow>
       
        
       
       
         <TableRow
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
             >
                
                <Button
                android:id="@+id/cpu_write"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="cpuWrite" />
            
            <Button
                android:id="@+id/cpu_send_cmd"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="0.5"
                android:text="sendCMD" 
                />
           
            
        </TableRow>
    </TableLayout>
</RelativeLayout>

【二. res下资源文件 arrays】

<?xml version="1.0" encoding="utf-8"?>  
<resources>  

 <string-array name="test1_arrays">             
        <item>删除MF</item>        
        <item>1.建立EF2001</item>
        <item>选择2001</item> 
        <item>2.建立EF2002</item>
        <item>选择2002</item>  
        <item>3.建立EF2003</item>
        <item>选择2003</item>  
    </string-array> 

</resources>  

【三.类】

package com.example.psam_demo;

import java.io.File;
import java.text.DecimalFormat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import test.Utils;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;


import com.android.rfid.PSAM;
import com.android.rfid.Tools;
import com.example.service.DeviceService;


public class UcpuSplitWriteActivity extends Activity  implements OnClickListener {
private EditText inputPath_data,cpu_receive_data,cpu_send_data;//接收返回数据
private Button cpu_reset_btn; //复位CPU卡
private Button cpu_write_btn,cpu_send_cmd;//cpu_write_btn写出文件内容      cpu_send_cmd发送指令
private Spinner cpu_cos_spinner;//Cos指令下拉框


private PSAM psam;   //PSAM对象,用于调用封装指令
private MyBroadcast myBroadcast;//广播接收者
public String activity = "com.example.psam_demo.UcpuSplitWriteActivity";
public int cmd_flag = 0;//指令操作状态




 // 线程池
      ExecutorService exec = Executors.newCachedThreadPool();
      final Semaphore semp = new Semaphore(1); //1 只能1个线程同时访问  5=只能5个线程同时访问
      
     
 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ucpu_split_write);
init();
}


private void init() {
cpu_cos_spinner = (Spinner) findViewById(R.id.cpu_cos_cmd);
inputPath_data = (EditText) findViewById(R.id.path);
cpu_receive_data = (EditText) findViewById(R.id.cpu_receive_data);
cpu_send_data= (EditText) findViewById(R.id.cpu_send_data);

cpu_reset_btn = (Button)findViewById(R.id.cpu_reset);
cpu_write_btn = (Button)findViewById(R.id.cpu_write);
cpu_send_cmd=(Button)findViewById(R.id.cpu_send_cmd);

cpu_reset_btn.setOnClickListener(this);
cpu_write_btn.setOnClickListener(this);
cpu_send_cmd.setOnClickListener(this);



// 添加COS指令选项
ArrayAdapter select_samAdapter = ArrayAdapter.createFromResource(this,
R.array.test1_arrays,
android.R.layout.simple_spinner_item);
select_samAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cpu_cos_spinner.setAdapter(select_samAdapter);
cpu_cos_spinner.setOnItemSelectedListener(new OnItemSelectedListener() {


@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
switch (position) {
case 0:
cpu_send_data.setText("800E000008");//删除MF  800e000008ffffffffffffffff
break;
//8k的cpu卡,最大使用空间,EF可写入字节为7600字节。 现在创建3个EF文件,每个文件大小2500字节=09c4。
case 1:
cpu_send_data.setText("80E02001072809c4F00EFF80");//建立标示符2001的EF文件, 2500(10进制)字节大小空间文件=09c4(16进制)
break;

case 2:
cpu_send_data.setText("00A4000002200100");//选择2001的EF文件
break;
case 3:
cpu_send_data.setText("80E02002072809c4F00EFF80");//建立标示符2002的EF文件, 2500(10进制)字节大小空间文件=09c4(16进制)
break;

case 4:
cpu_send_data.setText("00A4000002200200");//选择2002的EF文件
break;
case 5:
cpu_send_data.setText("80E02003072809c4F00EFF80");//建立标示符2003的EF文件, 2500(10进制)字节大小空间文件=09c4(16进制)
break;
case 6:
cpu_send_data.setText("00A4000002200300");//选择2003的EF文件
break;
default:
break;
}
}


@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub

}
});
}

@Override
protected void onResume() {
super.onResume();
psam = new PSAM(); // 实例化mpsam,用于调用协议封装命令
myBroadcast = new MyBroadcast();
IntentFilter filter = new IntentFilter();
filter.addAction(activity);
registerReceiver(myBroadcast, filter); // 注册广播接收者,广播接收Action=activity
}
@Override
protected void onPause() {
cmd_flag = 0;
unregisterReceiver(myBroadcast);   //失去焦点卸载广播注册    定义全局intent:stopService(sendToservice);


super.onPause();
}






public class MyRunnable implements Runnable {
byte[] imgArray ;
int a=0;
long ff=0;//一次写200字节,写图片的长度数据,算出要 写的次数
long yu=0;
public MyRunnable(int a,long ff, long yu,byte[] imgArray) {
this.a=a;
this.ff=ff;
this.yu=yu;
this.imgArray=imgArray;
}


@Override
public void run() {
             try {
semp.acquire(); // 获取许可

             
          Intent sendToservice = new Intent(UcpuSplitWriteActivity.this,DeviceService.class);  //用于发送指令
     
          if(a!=0){
        int offset=(200*(a-1))+3;//计算偏移量
        String offsetHexString=Integer.toHexString(offset);//偏移量
     String cmdHead="";//根据偏移量改变P1P2命令头
  if(offsetHexString.length()==1){
  cmdHead="00D6000"+offsetHexString+"C8";
  }else if(offsetHexString.length()==2){
  cmdHead="00D600"+offsetHexString+"C8";
  }else if(offsetHexString.length()==3){
  cmdHead="00D60"+offsetHexString+"C8";
  }else if(offsetHexString.length()==4){
  cmdHead="00D6"+offsetHexString+"C8";
  }
 
 
         byte[] cmdArray=null;
     if(a!=(ff+1)){ 
  cmdArray=Utils.copyArray(cmdHead,a,imgArray);
    
     cmd_flag = 42; //写出
     byte[] mycmd = psam.ucpu_send_cmd(cmdArray);
     sendToservice.putExtra("cmd", mycmd);  //封装指令
  UcpuSplitWriteActivity.this.startService(sendToservice); //发送指令到服务
                 Log.e("循环写出发送Accessing: " +a , "=="+Tools.Bytes2HexString(cmdArray, cmdArray.length));
               try {
   Thread.sleep(3000);
   } catch (InterruptedException e) {e.printStackTrace();}
   
    }else{
     String lastDataLength=Integer.toHexString((int)yu);//最后一次要写的剩余数据长度
if(lastDataLength.length()==1){
lastDataLength="0"+lastDataLength;
}
 
 cmdHead=cmdHead.replaceAll("C8", lastDataLength);
     cmdArray=Utils.copyArrayYu(cmdHead.length(),a,yu,imgArray);
     byte[] testArray  = Utils.zuArrayYu(cmdHead,cmdArray);
     
     cmd_flag = 42; //写出
   byte[] mycmd = psam.ucpu_send_cmd(testArray);
   sendToservice.putExtra("cmd", mycmd);  //封装指令
       UcpuSplitWriteActivity.this.startService(sendToservice); //发送指令到服务
               Log.e("写出剩余的发送Accessing: " +a , "=="+Tools.Bytes2HexString(mycmd, mycmd.length));
               try {
   Thread.sleep(3000);
   } catch (InterruptedException e) {e.printStackTrace();}
 
   
     
//             try {//写完了
//            exec.shutdownNow();// 调用这个方法后,立即停止执行者的运行。返回待执行的Task。
//            } catch (RejectedExecutionException e) {
//                e.printStackTrace();
//            } 
            Intent serviceIntent = new Intent();
serviceIntent.setAction(activity);
serviceIntent.putExtra("result", "over");
sendBroadcast(serviceIntent);

Thread.yield();  //线程让步。  
               
               
               
               
    }
           
           
           
           
           
      }else{
      //a=0,首次写入长度3个字节,2个数字占1字节,所以 不足的 补长度C:
     String head="";
             if(String.valueOf(imgArray.length).length()==1){
              head="00D6000003"+ String.valueOf(imgArray.length)+"CCCCC";//小于200不会出现
             }else if (String.valueOf(imgArray.length).length()==2){
              head="00D6000003"+ String.valueOf(imgArray.length)+"CCCC";
             }else if(String.valueOf(imgArray.length).length()==3){
              head="00D6000003"+ String.valueOf(imgArray.length)+"CCC";
             }else if(String.valueOf(imgArray.length).length()==4){
              head="00D6000003"+ String.valueOf(imgArray.length)+"CC";
             }else if(String.valueOf(imgArray.length).length()==5){
              head="00D6000003"+ String.valueOf(imgArray.length)+"C";//大于7600不会出现
             }else{
             }
             //写出
 cmd_flag = 42;
 byte[] mycmd = psam.ucpu_send_cmd(Tools.HexString2Bytes(String.valueOf(head)));
 sendToservice.putExtra("cmd", mycmd);  //封装指令
 UcpuSplitWriteActivity.this.startService(sendToservice); //发送指令到服务
 Log.e(a+"首次写入长度3个字节: "  +"=="+ Tools.Bytes2HexString(mycmd, mycmd.length), "=="+head+"");
     try {
 Thread.sleep(3000);
 } catch (InterruptedException e) {e.printStackTrace();}
      }
   
            // semp.release();// 收到串口返回9000写成功释放
             //availablePermits()指的是当前信号灯库中有多少个可以被使用
             } catch (InterruptedException e) {
  e.printStackTrace();
  exec.shutdownNow();  //中止线程池中全部的线程的执行。  
  }    
}

}
@Override
public void onClick(View v) {
// 给服务发送广播,内容为com.example.psam_demo.PSAM_Activity
Intent ac = new Intent();
ac.setAction("com.example.service.DeviceService");
ac.putExtra("activity", activity);
sendBroadcast(ac);

cpu_receive_data.setText("");//清空内容
byte [] cmd = null;  //用于存放指令
Intent sendToservice = new Intent(UcpuSplitWriteActivity.this,DeviceService.class);  //用于发送指令


switch (v.getId()) {
case R.id.cpu_reset:
cmd_flag = 1;
cmd = psam.ucpu_open();
if(cmd != null){
Log.e("cpu上电==", Tools.Bytes2HexString(cmd, cmd.length));
}else{

}
break;
case R.id.cpu_write:
//输入文件名+后缀    把要写的文件放到指定目录下。
   byte[] imgArray=getFileArray();
   if(imgArray!=null){
 if(imgArray.length<7600){
    long len= imgArray.length;
double pi =len/200;// 
String nn=new DecimalFormat("0000").format(pi);
long ff= Long.parseLong(nn);//一次写200字节,写图片的长度数据,算出要 写的次数
long yu=len%200;
if(ff==0&&yu>0){//文件小与200,既不会超过000000 6位数长度,占3字节。不够的用C补位。
//写入的数据16进制长度,数据少于200,0-C8之间,占1或2位。 如
//1.如需要写入的数据为:1122334455667788  =8个长度。
//2.写入内容=前三位数据长度+数据内容。  08CCCC1122334455667788 共11位数据长度。 
//3.CMD="00D600001108CCCC1122334455667788";
 String head="";
             if(String.valueOf(yu).length()==1){
              head= String.valueOf(yu)+"CCCCC";//小于200不会出现
             }else if (String.valueOf(yu).length()==2){
              head= String.valueOf(yu)+"CCCC";
             }else if(String.valueOf(yu).length()==3){
              head= String.valueOf(yu)+"CCC";
             }
             
             StringcmdHead="";
           String datalen=Integer.toHexString((int)yu+3);//欲写数据长度转16进制  数据不超200=C8
if(datalen.length()==1){
             cmdHead="00D600000"+datalen+head;
             }else if(datalen.length()==2){
             cmdHead="00D60000"+datalen+head;
             }
byte[] cmdArray=Utils.copyArrayData(cmdHead,yu,imgArray);
Log.e(datalen+"写出小于200字节文件"+"=="+cmdHead, yu+"=="+Tools.Bytes2HexString(cmdArray, cmdArray.length));
cmd_flag = 42;
cmd = psam.ucpu_send_cmd(cmdArray);
  Toast.makeText(getApplicationContext(), "写出完成", Toast.LENGTH_SHORT).show();
  cpu_receive_data.setText("write over !");  
}else{//大于200,循环写出
synchronized(this){

for(int a=0;a<=(ff+1);a++){

// ff=每次写入200字节,要循环的次数,从1到ff。for循环定义a=0,因为首次要写入3字节6位长度的数据总长度标记,所以要从0开始写。

//MyRunnable中 int offset=(200*(a-1))+3;//计算偏移量 ,当a=1时为第二次写入,第一次写入前三字节的数据总长度,第二次才开始正式写入信息数据,所以第二次写时,要在3的位置后面写200字节,需要偏移3位,写200字节=(200*(1-1)+3)=偏移3位,数组拷贝200字节 System.arraycopy(imgArray, 200*(a-1), command, targets.length, 200)当a=1时,从数组第0位开始拷贝,拷贝200。 

// 第(ff+1)次为要循环写入200字节后,所剩余不足200字节的余数据。

    MyRunnable myTest = new MyRunnable(a,ff,yu,imgArray);
    Thread thread = new Thread(myTest);
    thread.start();
    exec.execute(myTest);
}//for
}//syn




}





 }else{
 Toast.makeText(getApplicationContext(), "文件过大!", Toast.LENGTH_SHORT).show();
}
 }else{
 Toast.makeText(getApplicationContext(), "请输入文件名+后缀", Toast.LENGTH_SHORT).show();
 }


//  // 退出线程池
//   exec.shutdown();


break;

case R.id.cpu_send_cmd://cpu发送数据
cmd_flag = 4;
String data = cpu_send_data.getText().toString();
cmd = psam.ucpu_send_cmd(Tools.HexString2Bytes(data));
if(cmd != null){
Log.e("cpu发送指令", Tools.Bytes2HexString(cmd, cmd.length));
}else{

}
break;
default:
break;
}
sendToservice.putExtra("cmd", cmd);  //封装指令
UcpuSplitWriteActivity.this.startService(sendToservice); //发送指令到服务
}




 
private  byte[] getFileArray() {
String path="";
String pathDirectory=MyApplication.filePath+"/";
if(inputPath_data.getText().toString()!=null&&!inputPath_data.getText().toString().equals("")){
path= pathDirectory+inputPath_data.getText().toString();
}
long fileLength = 0;//文件长度
File flie = new File(path);
    if (!flie.isDirectory() && flie.exists()) {
        fileLength = flie.length();
        } else {//file not  exists()
        fileLength = 0;
return null;
    }
    byte[] imgArray=Utils.readData(path,fileLength);
    Log.e("读取我的文件", Tools.Bytes2HexString(imgArray, imgArray.length));
cpu_send_data.setText(path);//选择2002的EF文件
return imgArray;
}








// 广播接收者,用于接收串口 服务返回的数据,并更新UI,    串口接收数据服务类为DeviceService.class
private class MyBroadcast extends BroadcastReceiver{
SharedPreferences preferences = getSharedPreferences("cmd_backData", Context.MODE_PRIVATE);
   
@Override
public void onReceive(Context context, Intent intent) {
String receivedata = intent.getStringExtra("result"); // 服务返回的数据
if(receivedata.equals("over")){
cpu_receive_data.setText("write over !");
}

if (receivedata != null&&!receivedata.equals("over")) {
byte []receive_buffer = Tools.HexString2Bytes(receivedata);
Log.e("发送CMD返回数据:"+cmd_flag+"=="  + "  receivedata", receivedata);
switch (cmd_flag) {
case 42:
byte [] receiver_buffer_DF = Tools.HexString2Bytes(receivedata);
    byte []receiver_data_DF = psam.resolveDataFromDevice(receiver_buffer_DF);
    if(receiver_data_DF != null){
    String response=Tools.Bytes2HexString(receiver_data_DF, receiver_data_DF.length);
    cpu_receive_data.setText(response);
   
   
    Log.e("t--CMD返回数据:"+response+"=="  + "  receivedata", receivedata);
    if(response.equals("9000")){
    semp.release();
    }
    }
   
   
break;
case 1:
byte []active_buffer = Tools.HexString2Bytes(receivedata);
byte []active_data = psam.resolveDataFromDevice(active_buffer);
if(active_data != null){
cpu_receive_data.setText(Tools.Bytes2HexString(active_data, active_data.length));
//Toast.makeText(getApplicationContext(), "激活卡片成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(), "激活卡片失败", Toast.LENGTH_SHORT).show();
}
break;

case 4:
byte [] receiver_buffer4 = Tools.HexString2Bytes(receivedata);
    byte []receiver_data4 = psam.resolveDataFromDevice(receiver_buffer4);
    if(receiver_data4 != null){
    String response=Tools.Bytes2HexString(receiver_data4, receiver_data4.length);
    cpu_receive_data.setText(response);
    }else{//Data failure
    cpu_receive_data.setText("");
    }
break;

default:
break;
}
}

}


}

}



【四.应用生成目录】

public class MyApplication   extends Application{
 public static Context context;
 public static String filePath;
 @Override
   public void onCreate() {
       super.onCreate();
       context = getApplicationContext();
       MakeAppDirectory();
   }
private void MakeAppDirectory() {
        filePath=Environment.getExternalStorageDirectory()+"/PSAM_Demo";//内部目录
        File file = null;
           try {
               file = new File(filePath);
               if (!file.exists()) {
                   file.mkdir();
               }else{
                   file.delete();
               }
           } catch (Exception e) {
            e.printStackTrace();
           }

}
}


【五.串口读写服务结合工程lib库使用】

package com.example.service;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Timer;




import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;


import com.android.rfid.PSAM;
import com.android.rfid.Tools;
/**
 * 设备服务,用于在后台运行,发送命令和接收数据
 * 在服务初始化时,执行串口打开,设备电源开启,
 * 获取串口输入输出流
 * 启动读数据线程
 * @author Administrator
 *
 */
public class DeviceService extends Service {


protected PSAM mSerialPort;//用于调用本地方法
protected OutputStream mOutputStream;  //串口输出流
private InputStream mInputStream;      //串口输入流
private ReadThread mReadThread;  //读线程
private final int port = 14;//串口号3


private Boolean run = true; // 线程中断信号
private String data = null; // 返回的数据
private StringBuffer data_buffer = new StringBuffer();
// private Timer sendData;
private MyReceiver myReceive;  //广播接收者
//射频开关计时器
private Timer stopRF;


public String activity = null; // 回传数据的activity


/**
*  读线程 ,读取设备返回的信息,将其回传给发送请求的activity
* @author Jimmy Pang
*
*/
private class ReadThread extends Thread {


@Override
public void run() {
super.run();
while (run) {
int size;
try {
byte[] buffer = new byte[300];//读取数据
if (mInputStream == null)
return;
size = mInputStream.read(buffer);
if (size > 0) {


data = Tools.Bytes2HexString(buffer, size);
data_buffer.append(data);
data = null;
if(data_buffer.toString().length() > 10){
String dataLen = data_buffer.substring(2, 6); // 取得数据包的长度
//Log.e("datalength", dataLen+"**" +data_buffer.toString());
if(Tools.checkData(dataLen, data_buffer.toString())){
// Log.e("DeviceService data", data_buffer.toString());

Intent serviceIntent = new Intent();
serviceIntent.setAction(activity);
serviceIntent.putExtra("result", data_buffer.toString());
data_buffer.setLength(0);
sendBroadcast(serviceIntent);
}else{
// Log.e("eeeeeeeeeeeeeeeeeeeeeeeee888888", "== "+activity);

}
}else{
data_buffer.setLength(0);
}
 
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}




@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}


@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();


init();


}


private void init(){
Log.e("service on create", "service on create");
try {
mSerialPort = new PSAM(port, 115200); // 打开串口,设备的端口号设置为3,波特率为115200
Log.e("mSerialPort", mSerialPort + "");
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if(mSerialPort == null){  //没找到设备
// Toast.makeText(getApplicationContext(), "无法找到设备", Toast.LENGTH_SHORT).show();
Log.e("", "aaaaa");
return;
}
mSerialPort.PowerOn_HFPsam(); // 开启电源
mOutputStream = mSerialPort.getOutputStream();
mInputStream = mSerialPort.getInputStream();


myReceive = new MyReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.example.service.DeviceService");
registerReceiver(myReceive, filter);
// 注册Broadcast Receiver,用于关闭Service
// sendData = new Timer();
/* Create a receiving thread */
mReadThread = new ReadThread();
mReadThread.start(); // 开启读线程
Log.e("DeviceService", "start thread");


}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
byte[] cmd_arr = intent.getByteArrayExtra("cmd");
if (cmd_arr == null)
return 0; // 没收到命令直接返回
// Log.e("CMD", Tools.Bytes2HexString(cmd_arr, cmd_arr.length));

try {
mOutputStream.write(cmd_arr); // 发送命令
Log.e("WRITE", "SUCCESS");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


return 0;
}


@Override
public void onDestroy() {
if (mReadThread != null)
run = false; // 销毁线程
Log.e("销毁线程000000000", "start thread");
mSerialPort.PowerOff_HFPsam(); // 关闭电源
mSerialPort.close(port); // 关闭串口
unregisterReceiver(myReceive); // 卸载注册
super.onDestroy();
}


/**
*  广播接受者
* @author Jimmy Pang
*
*/
private class MyReceiver extends BroadcastReceiver {


@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String ac = intent.getStringExtra("activity");
if(ac!=null) 
Log.e("receive activity", ac);
activity = ac; // 获取activity
if (intent.getBooleanExtra("stopflag", false))
stopSelf(); // 收到停止服务信号
Log.e("stop service", intent.getBooleanExtra("stopflag", false)
+ "");


}


}


}



【六.帮助类 拷贝数组 循环获取200字节】

public class Utils {
private static byte[] readImage(InputStream input)throws  Exception {
byte  imagebyte[]=null;
byte buffer[]=new byte[1024];
ByteArrayOutputStream  out=new ByteArrayOutputStream();
while(input.read(buffer)!=-1){
out.write(buffer, 0, buffer.length);
}
out.close();
input.close();
imagebyte=out.toByteArray();
return imagebyte;
}
public static byte[] readData(String path,long fileLength){
byte[] buffer = null;
File file = new File(path);
       if (!file.isDirectory() && file.exists()) {
           try {
               InputStream in = new FileInputStream(file);
             buffer=new byte[(int) file.length()];
               try {
               int len=in.read(buffer);
               
//imagebyte=readImage(in);
//String msg = new String(imagebyte, 0, imagebyte.length, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}


           } catch (FileNotFoundException e) {
               e.printStackTrace();
           }
       }
 
return buffer;  
}
 
 //十六进制转byte
  public static byte[] HexString2Bytes(String src) {
  int len = src.length() / 2;
  byte[] ret = new byte[len];
  byte[] tmp = src.getBytes();


  for (int i = 0; i < len; i++) {
  ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
  }
  return ret;
  }
  public static byte uniteBytes(byte src0, byte src1) {
   byte _b0 = Byte.decode("0x" + new String(new byte[]{src0})).byteValue();
   _b0 = (byte)(_b0 << 4);
   byte _b1 = Byte.decode("0x" + new String(new byte[]{src1})).byteValue();
   byte ret = (byte)(_b0 ^ _b1);
   return ret;
 }
 public static byte[] copyArray(String P,int i,byte[] imgArray) {
     byte[] targets =HexString2Bytes(P);
             // 循环拷贝200字节
         byte[] command = new byte[targets.length +200];//
         System.arraycopy(targets, 0, command, 0, targets.length);
        // System.arraycopy(imgArray, imgArray.length-(200*i), command, targets.length, 200);
       //拷贝imgArray  每次开始位置为imgArray.length-(200*i)
         System.arraycopy(imgArray, 200*(i-1), command, targets.length, 200);
      
         return command;
   }  
// System.arraycopy(src, srcPos, dst, dstPos, length);
// src:源数组;
// srcPos:源数组要复制的起始位置;
// dest:目的数组;
// destPos:目的数组放置的起始位置;
// length:复制的长度。
 public static byte[] copyArrayYu(long len, int i,long yu, byte[] imgArray) {
// int[] fun ={0,1,2,3,4,5,6};
// System.arraycopy(fun,0,fun,3,3);
//  结果为:{0,1,2,0,1,2,6};
//  long len= targets.length;
 byte[] yuArray = new byte[(int)yu];
 System.arraycopy(imgArray, (int) (imgArray.length-yu), yuArray,0, (int)yu);
     //意思是:拷贝imgArray中的数据 ,从第(imgArray.length-yu)开始拷贝,到目标数组yuArray,从标记位0开始,拷贝到xx个长度结束。
 return yuArray;
}    
   
 public static byte[] zuArrayYu(String P,byte[] randomNumber ) {//External certification
 byte[] targets =HexString2Bytes(P);
     byte[] externalAuthCommand = new byte[targets.length + randomNumber.length];
     System.arraycopy(targets, 0, externalAuthCommand, 0, targets.length);
     System.arraycopy(randomNumber, 0, externalAuthCommand, targets.length, randomNumber.length);
     return externalAuthCommand;
 }
public static byte[] copyArrayData(String cmdHead, long yu, byte[] imgArray) {
 byte[] targets =HexString2Bytes(cmdHead);
    byte[] externalAuthCommand = new byte[targets.length + (int)yu];
    System.arraycopy(targets, 0, externalAuthCommand, 0, targets.length);
    System.arraycopy(imgArray, 0, externalAuthCommand, targets.length, (int)yu);
    return externalAuthCommand;
}
   
   

}

原创粉丝点击