Java代码翻写成OC样例

Java代码

// TranslateData
public void translateData(byte[] data, int size) {
    for (int i = 0; i < size; i++) {
        byte b = data[i];
        if (head_count < HEAD_LENGTH) {
            switch (head_count) {
                case 0:
                    if (b == HOST) {
                        head_count++;
                        commandBean.setHost(b);
                    } else {
                        head_count = 0;
                    }
                    break;
                case 1:
                    commandBean.setCommand(b);
                    head_count++;
                    break;
                case 2:
                    commandBean.setSequence(b);
                    head_count++;
                    break;
                case 3:
                    commandBean.setOption(b);
                    head_count++;
                    break;
                case 4:
                    commandBean.setLength(b);
                    head_count++;
                    data_count = 0;
                    break;
                default:
                    break;
            }
        } else {
            if (data_count < commandBean.getLength()) {
                temp[data_count++] = b;
            } else {
                byte bcc = Common.bcc(temp, 0, commandBean.getLength());
                if (bcc == b) {
                    commandBean.setData(temp);
                    doCommand(commandBean);
                }
                head_count = 0;
                data_count = 0;
            }
        }
    }
}
// commandBean
public class CommandBean
implements Serializable
{
    private byte command;
    private byte[] data;
    private byte host;
    private byte length;
    private byte option;
    private byte sequence;
    
    public byte getCommand()
    {
      return command;
    }
    
    public byte[] getData()
    {
      return data;
    }
    
    public byte getHost()
    {
      return host;
    }
    
    public int getLength()
    {
      return Common.byte2Int(length);
    }
    
    public byte getOption()
    {
      return option;
    }
    
    public byte getSequence()
    {
      return sequence;
    }
    
    public void setCommand(byte paramByte)
    {
      command = paramByte;
    }
    
    public void setData(byte[] paramArrayOfByte)
    {
      data = paramArrayOfByte;
    }
    
    public void setHost(byte paramByte)
    {
      host = paramByte;
    }
    
    public void setLength(byte paramByte)
    {
      length = paramByte;
    }
    
    public void setOption(byte paramByte)
    {
      option = paramByte;
    }
    
    public void setSequence(byte paramByte)
    {
      sequence = paramByte;
    }
}
// 有关调用方法
translateData(buffer, bytes);

我们来看看buffer的具体样例:
a0780000 02040004
a0800000 13140080 30005555 33b2ddd9 01400000 0000be92 4c
a0800000 130d0080 30005555 33b2ddd9 01400000 0000be92 55
a0800000 13120080 30005555 33b2ddd9 01400000 0000be92 4aa08000 00130500 803000bb bb33b2dd d9014000 00000083 3ac8
a0800000 130e0080 3000bbbb 33b2ddd9 01400000 0000833a c3a08000 00131100 80300055 5533b2dd d9014000 000000be 9249
我们用a0780000 02040004来进行举例

// a0|78|00|00|02|04|0004| 我们这样来进行拆分
// 首先我们先来翻写translateData的Objective-C
#pragma mark -执行命令
- (void) doCommand:(struct DataBean) cmd {
    // int result;
    switch (cmd.command) {
        case CMD_GET_VERSION:
            [TopToast showToptoastWithText:@"获得版本!" duration:1 height:64 backGroundColor:[UIColor blackColor] alpha:1.0];
        break;
        case CMD_ERROR:
            [TopToast showToptoastWithText:@"系统错误!" duration:1 height:64 backGroundColor:[UIColor blackColor] alpha:1.0];
        break;
        case CMD_READ_LABEL:
            [TopToast showToptoastWithText:@"读取标签!" duration:1 height:64 backGroundColor:[UIColor blackColor] alpha:1.0];
        break;
        case CMD_WRITE_LABEL:
            [TopToast showToptoastWithText:@"写入标签!" duration:1 height:64 backGroundColor:[UIColor blackColor] alpha:1.0];
        break;
        case CMD_INVENTORY:
            [TopToast showToptoastWithText:@"查询标签!" duration:1 height:64 backGroundColor:[UIColor blackColor] alpha:1.0];
        break;
        case CMD_CLEAR_CACHE:
            [TopToast showToptoastWithText:@"清除缓存!" duration:1 height:64 backGroundColor:[UIColor blackColor] alpha:1.0];
        break;
        case CMD_SET_OUTPUT:
            [TopToast showToptoastWithText:@"设置功率!" duration:1 height:64 backGroundColor:[UIColor blackColor] alpha:1.0];
        break;
        case CMD_GET_OUTPUT:
            [TopToast showToptoastWithText:@"获取功率!" duration:1 height:64 backGroundColor:[UIColor blackColor] alpha:1.0];
        break;
        case CMD_BATTERY:
            [TopToast showToptoastWithText:@"获取电量!" duration:1 height:64 backGroundColor:[UIColor blackColor] alpha:1.0];
        break;
        case CMD_CHARGING:
            // TODO
        break;
        default:
            break;
    }
}

#pragma mark- 数据解析
- (void) translateData: (Byte[])data size:(long)size {
    for (int i = 0; i < size; i++) {
        Byte b = data[i];
        if (_head_count < HEAD_LENGTH) {
            switch (_head_count) {
                case 0:
                    if (b == HOST) {
                        _head_count++;
                        _dataBean.host = b;
                    } else {
                        _head_count = 0;
                    }
                break;
                case 1:
                    _dataBean.command = b;
                    _head_count++;
                break;
                case 2:
                    _dataBean.sequence = b;
                    _head_count++;
                break;
                case 3:
                    _dataBean.option = b;
                    _head_count++;
                break;
                case 4:
                    _dataBean.length = b;
                    _head_count++;
                    _data_count = 0;
                break;
            }
        } else {
            if (_data_count < _dataBean.length) {
                _temp[_data_count++] = b;
            } else  {
                // 暂时不进行BCC校验
                _dataBean.data = _temp;
                [self doCommand:_dataBean];
                _head_count = 0;
                _data_count = 0;
            }
        }
    }
}

Android开发之BroadcastReceiver

BroadCastReceiver

广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是通过调用Context.sendBroadcast() 、 Context.sendOrderedBroadcast() 来实现的。通常一个广播 Intent 可以被订阅了此 Intent 的多个广播接收者所接收。
广播是一种广泛运用的在应用程序之间传输信息的机制 。而 BroadcastReceiver 是对发送出来的广播进行过滤接收并响应的一类组件;

  • BroadCastReceiver的机制
  • 在 Android 里面有各种各样的广播,比如电池的使用状态,电话的接收和短信的接收都会产生一个广播,应用程序开发者也可以监听这些广播并做出程序逻辑的处理。
    广播的步骤

    public class MyBroadcastReceiver extends BroadcastReceiver {
        // action 名称
        String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" ;
        public void onReceive(Context context, Intent intent) {
     
           if (intent.getAction().equals( SMS_RECEIVED )) {
               // 相关处理 : 地域变换、电量不足、来电来信;
           }
        }
    }
    < receiver android:name = ".MyBroadcastReceiver" >
    < intent-filter android:priority = "1000" >      
    < action android:name = " android.provider.Telephony.SMS_RECEIVED" />
    
     当然了需要权限 :
    < uses-permission android:name = "android.permission.RECEIVE_SMS" />
    < uses-permission android:name = "android.permission.SEND_SMS" />
    
    private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
           @Override
           public void onReceive(Context context, Intent intent) {
               // 相关处理,如收短信,监听电量变化信息
           }
    };
    IntentFilter intentFilter = new IntentFilter( "android.provider.Telephony.SMS_RECEIVED " );
    registerReceiver( mBatteryInfoReceiver , intentFilter);
    

    Unity3d中SendMessage – Android和Unity的交互

      • UnityPlayer的SendMessage

    SendMessage

    
    // paramString1 表示挂载脚本的对象
    // paramString2 表示脚本中调用的方法名
    // paramString3 传参数
    UnityPlayer.UnitySendMessage(paramString1, paramString2, paramString3);
    
      AndroidJavaClass和AndroidJavaObject
    
    using UnityEngine;
    using System.Collections;
    public static class AndroidUtils {
    	public static AndroidJavaClass unityOverrideClass;
    	public static AndroidJavaClass UnityOverrideClass {
    		get {
    			if (unityOverrideClass == null) {
    				unityOverrideClass = new AndroidJavaClass ("com.xxx.xxxx.xxxxActivity");
    			}
    			return unityOverrideClass;
    		}
    	}
    
    	public static AndroidJavaObject SDK {
    		get {
    			return UnityOverrideClass.CallStatic ("GetSDK", new object[0]);
    		}
    	}
    }
    

    同时需要我们Android封装Jar包,以及AndroidManifest.xml,XML中定义的Activity所需要的res也需要。将这些内容放置到Plugins中:

    Unity调用Android的方法如下

    
    AndroidUtils.SDK.Call("AndroidMethodName", args);
    

    AndroidManifest.xml示例

    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="com.xx.xxxx" platformBuildVersionCode="22" platformBuildVersionName="5.1.1-1819727">
     <supports-screens android:largeScreens="true" android:normalScreens="false" android:requiresSmallestWidthDp="600" android:smallScreens="false" android:xlargeScreens="true"/>
     <uses-feature android:glEsVersion="0x00020000"/>
     <supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture"/>
     <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
     <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false"/>
     <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false"/>
     <uses-permission android:name="com.android.vending.CHECK_LICENSE"/>
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.WAKE_LOCK"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
     <uses-permission android:name="android.permission.BLUETOOTH"/>
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.CAMERA"/>
     <android:uses-permission android:name="android.permission.READ_PHONE_STATE"/>
     <application android:allowBackup="true" android:icon="@drawable/app_icon" android:isGame="true" android:label="@string/app_name" android:largeHeap="true" android:name="com.xxx.xxxx.BLApplication" android:supportsRtl="true" android:theme="@style/UnityThemeSelector">
     <activity android:configChanges="locale|fontScale|keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode" android:exported="true" android:label="@string/app_name" android:launchMode="singleTask" android:name="com.xx.xxx.SDKNativeActivity" android:screenOrientation="sensorLandscape">
     <meta-data android:name="unityplayer.UnityActivity" android:value="true"/>
     <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false"/>
     <intent-filter>
     <action android:name="android.intent.action.MAIN"/>
     <category android:name="android.intent.category.LAUNCHER"/>
     </intent-filter>
     </activity>
     </application>
    </manifest> 
    

    记录一次代码分析(2)

    续接上节,我们这次主要分析的是ManagePlayerActivity

  • 成员变量
  • 
      private static LoginListener listener;
      private Button btnAddPlayer;
      private Button btnBack;
      private Button btnEditPlayer;
      private boolean isManagePlayer = true;
      private LinearLayout llFilters;
      private PlayersAdapter mPlayersAdapter;
      private GridView mPlayersGridView;
      private List playersList;
      private RelativeLayout rlRootView;
      private SharedPrefUtil sharedPrefUtil;
      ...
    
  • 主要成员函数
    • onCreate
    
      protected void onCreate(Bundle paramBundle)
      {
        super.onCreate(paramBundle);
        setContentView(R.layout.activity_manage_player);
        sharedPrefUtil = new SharedPrefUtil(this);
        ...
        try
        {
          ...
          mPlayersGridView.setOnItemClickListener(new AdapterView.OnItemClickListener()
          {
            public void onItemClick(AdapterView paramAnonymousAdapterView, View paramAnonymousView, int paramAnonymousInt, long paramAnonymousLong)
            {
              if (isManagePlayer)
              {
                paramAnonymousAdapterView = mPlayersAdapter.getItem(paramAnonymousInt);
                paramAnonymousView = new Intent(ManagePlayerActivity.this, AddEditPlayerActivity.class);
                paramAnonymousView.addFlags(65536);
                paramAnonymousView.putExtra("EXTRA_PLAYER", paramAnonymousAdapterView);
                startActivityForResult(paramAnonymousView, 0);
              }
              ...
              if (BluetoothUtil.isPlaysetConnected())
              {
                ...
                return;
              }
              paramAnonymousAdapterView = new Intent(ManagePlayerActivity.this, PlaysetScanActivity.class);
              ...
              startActivityForResult(paramAnonymousAdapterView, 0);
            }
          });
          ...
          return;
        }
        catch (Exception paramBundle)
        {
          for (;;)
          {
            paramBundle.printStackTrace();
          }
        }
      }
    

    下面来看下PlaysetScanActivity主要用来Scan!
    PlaysetScanActivity同样继承BluetoothBaseActivity。

  • 成员变量
  • 
      private static final int REQUEST_ENABLE_BT = 1;
      private static final long SCAN_PERIOD = 10000L;
      private static final String TAG = PlaysetScanActivity.class.getName();
      private BluetoothStateReceiver bluetoothStateReceiver;
      ...
      private FlowLayout flowLayout;
      private boolean isAudioPlayed = false;
      private boolean isLettersRead = false;
      private boolean isPaused;
      private boolean isPermissionGranted = true;
      private boolean isPlaysetSelected = false;
      ...
      private BluetoothAdapter mBluetoothAdapter;
      private String mDeviceAddress;
      private String mDeviceName;
      private Handler mHandler;
      // 蓝牙设备列表
      private ArrayList mLeDevices = new ArrayList();
    

    这个类也非常重要,我想我们离成功就更近一步了。有关蓝牙(BLE)的相关内容,博客的文章也有所提及,我这边回慢慢完善。

  • 重要成员函数
    • onCreate
    
      public void onCreate(Bundle paramBundle)
      {
        ...
        // 蓝牙接收器
        bluetoothStateReceiver = new BluetoothStateReceiver();
        // 判断是否支持BLE
        if (!getPackageManager().hasSystemFeature("android.hardware.bluetooth_le"))
        {
          ...
          finish();
        }
        // 获取蓝牙适配器
        mBluetoothAdapter = ((BluetoothManager)getSystemService("bluetooth")).getAdapter();
        if (mBluetoothAdapter == null)
        {
          // 蓝牙不支持
          return;
        }
        if (sharedPrefUtil.getBoolean("IS_IDLE_TIME"))
        {
          //
        }
        paramBundle = new IntentFilter("android.bluetooth.adapter.action.STATE_CHANGED");
        // 注册蓝牙广播
        registerReceiver(bluetoothStateReceiver, paramBundle);
      }
    
      onResume
    
      protected void onResume()
      {
        ...
        isPaused = false;
        // 蓝牙关闭
        if (!mBluetoothAdapter.isEnabled())
        {
          ...
        }
        // 蓝牙没有连接
        if ((!BluetoothUtil.isPlaysetConnected()) && (!BluetoothUtil.getFirmwareUpdateState()) && (!BluetoothUtil.isBootModeEnabled()))
        {
          isPlaysetSelected = false;
          isAudioPlayed = false;
          if (!mScanning) {
            new Handler().postDelayed(new Runnable()
            {
              public void run()
              {
                PlaysetScanActivity.this.scanLeDevice(true);
              }
            }, 1000L);
          }
        }
      }
    

    开始扫描设备进行连接scanLeDevice

    
      private void scanLeDevice(boolean paramBoolean)
      {
        if (mBluetoothAdapter == null) {
          return;
        }
        if (paramBoolean)
        {
          mScanning = true;
          // 清空当前列表
          clearScanList();
          mHandler.postDelayed(new Runnable()
          {
            public void run()
            {
              if ((mScanning) && (!isPlaysetSelected))
              {
                ...
              }
            }
          }, 10000L);
          mHandler.postDelayed(new Runnable()
          {
            public void run()
            {
              // 设备不存在
              if ((mLeDevices.size() == 0) && (!isPlaysetSelected) && (!BluetoothUtil.isPlaysetConnected())) {
                ...
              }
              BluetoothDevice localBluetoothDevice;
              ArrayList localArrayList;
              do
              {
                do
                {
                  return;
                } while ((getIntent().hasExtra("EXTRA_CHOOSE_PLAYSET")) || (isPlaysetSelected) || (sharedPrefUtil.getStringSet("REMEMBER_PLAYSET").size() <= 0) || (flowLayout.getChildCount() != 1));
                localBluetoothDevice = (BluetoothDevice)flowLayout.getChildAt(0).getTag();
                localArrayList = new ArrayList();
                localArrayList.addAll(sharedPrefUtil.getStringSet("REMEMBER_PLAYSET"));
              } while ((!localArrayList.contains(localBluetoothDevice.getAddress())) || (isPaused));
              // 自动调用Click事件
              flowLayout.getChildAt(0).performClick();
            }
          }, 2000L);
          BluetoothAdapter localBluetoothAdapter = mBluetoothAdapter;
          UUID localUUID = Constants.FILTER_UUID_FOR_SCAN;
          // 设置回调
          BluetoothAdapter.LeScanCallback localLeScanCallback = mLeScanCallback;
          localBluetoothAdapter.startLeScan(new UUID[] { localUUID }, localLeScanCallback);
          return;
        }
        mScanning = false;
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
      }
    

    下面看下回调mLeScanCallback

    
      public void onLeScan(final BluetoothDevice paramAnonymousBluetoothDevice, int paramAnonymousInt, byte[] paramAnonymousArrayOfByte)
        {
          runOnUiThread(new Runnable()
          {
            public void run()
            {
              PlaysetScanActivity localPlaysetScanActivity;
              if (!isAudioPlayed)
              {
                localPlaysetScanActivity = PlaysetScanActivity.this;
                ...
              }
              for (boolean bool = true;; bool = false)
              {
                ...
                PlaysetScanActivity.this.addDevice(paramAnonymousBluetoothDevice);
                ...
                return;
              }
            }
          });
        }
      };
    

    我们此时加入了新的蓝牙连接设备对象addDevice

    
      private void addDevice(BluetoothDevice paramBluetoothDevice)
      {
        ...
        // 判断当前是否存在该设备
        if (!mLeDevices.contains(paramBluetoothDevice))
        {
          mLeDevices.add(paramBluetoothDevice);
          localView = getLayoutInflater().inflate(R.layout.device_item, null);
          localTextView = (TextView)localView.findViewById(R.id.tvDeviceName);
          String str = paramBluetoothDevice.getName();
          // 不存在设备则break;
          if ((str == null) || (str.length() <= 0)) {
            ...
          }
          localTextView.setText(str);
        }
        // 设置点击回调事件
        for (;;)
        {
          localView.setTag(paramBluetoothDevice);
          localView.setOnClickListener(new View.OnClickListener()
          {
            public void onClick(View paramAnonymousView)
            {
              // 用户选择了则return
              if (isPlaysetSelected) {
                return;
              }
              ...
              BluetoothDevice localBluetoothDevice = (BluetoothDevice)paramAnonymousView.getTag();
              if ((localBluetoothDevice == null) || (BluetoothUtil.isPlaysetConnected()))
              {
                ...
              }
              ...
              // 终止扫描
              SPPlaysetScanActivity.this.scanLeDevice(false);
              // 连接设备!!!
              boolean bool = BluetoothUtil.connectPlayset(mDeviceAddress, mDeviceName);
              ...
            }
          });
          ...
        }
      }
    

    该Activity中还包括检测硬件升级(checkFirmwareUpdate)、初始化UI(initUI)、bleLettersFromPlayset等函数。

    记录一次代码分析(1)


    入口Activity如下(由于有些涉及隐私,所以不展示):

    
      protected void onCreate(Bundle paramBundle)
      {
        super.onCreate(paramBundle);
        setContentView(R.layout.activity_splash_screen);
        getDeviceDimensions(this);
        sharedPrefUtil = new SharedPrefUtil(getApplicationContext());
        PlayerUtil.setSelectedPlayer(this, null);
        new Handler().postDelayed(new Runnable()
        {
          public void run()
          {
            if (sharedPrefUtil.getBoolean("LOGIN_USER_STATUS"))
            {
              localIntent = new Intent(SplashScreenActivity.this, ManagePlayerActivity.class);
              localIntent.putExtra("EXTRA_SELECT_PLAYER", true);
              localIntent.putExtra("EXTRA_IS_FIRST_TIME", true);
              startActivityForResult(localIntent, 0);
              return;
            }
            if (!sharedPrefUtil.getBoolean("HAVE_PLAYSET"))
            {
              localIntent = new Intent(SplashScreenActivity.this, BeforeStartActivity.class);
              startActivityForResult(localIntent, 0);
              return;
            }
            if (!sharedPrefUtil.getBoolean("DO_YOU_HAVE_ACCOUNT"))
            {
              localIntent = new Intent(SplashScreenActivity.this, HaveAccountActivity.class);
              startActivityForResult(localIntent, 0);
              return;
            }
            Intent localIntent = new Intent(SplashScreenActivity.this, LoginActivity.class);
            startActivityForResult(localIntent, 0);
          }
        }, SPLASH_TIME_OUT);
      }
    

    其中getDeviceDimensions为适配屏幕分辨率:

    
      public static void getDeviceDimensions(Activity paramActivity)
      {
        paramActivity = paramActivity.getWindowManager().getDefaultDisplay();
        Point localPoint = new Point();
        paramActivity.getSize(localPoint);
        Constants.setDeviceWidth(x);
        Constants.setDeviceHeight(y);
      }
    

    sharedPrefUtil用来本地存储,主要通过SharedPreferences来实现的,该程序主要包含的本地存储对象为:

    
    BATTER_SAVER
    DO_YOU_HAVE_ACCOUNT
    FILE_PATH
    FIRMWARE_RIVISION
    FIRMWARE_VERSION
    HARDWARE_RIVISION
    HAVE_PLAYSET
    IS_ALL_SET
    IS_IDLE_TIME
    LOGIN_USER_ID
    LOGIN_USER_INFO
    LOGIN_USER_STATUS
    LOGIN_USER_TOKEN
    PLAYERS_LIMIT
    PLAYSET_ADDRESS
    PLAYSET_IDLE_TIME
    PLAYSET_MANUFACTURER
    PLAYSET_MODEL
    PLAYSET_NAME
    PRIVACY
    REMEMBER_PLAYSET
    SELECTED_PLAYER
    TERMS_AND_CONDITIONS
    USER_ID
    USER_NAME
    USER_PASSWORD
    

    如果存在LOGIN_USER_STATUS则跳转ManagePlayerActivity,并传递参数EXTRA_SELECT_PLAYER和EXTRA_IS_FIRST_TIME参数。如果没有用户则需要创建用户,有用户需要登录。下一步主要来看下ManagePlayerActivity。

  • ManagePlayerActivity
  • 类定义及继承关系

    
      public class ManagePlayerActivity
        extends BluetoothBaseActivity
        implements View.OnClickListener, ApiCallListener {
         ...
      }
    

    接口ApiCallListener定义如下

    
    public abstract interface ApiCallListener
    {
      public abstract void onFailure(Object paramObject);
      public abstract void onResponse(Object paramObject);
    }
    

    ManagePlayerActivity继承BluetoothBaseActivity

  • BluetoothBaseActivity
  • 
    public abstract class BluetoothBaseActivity
      extends AppCompatActivity
      implements BluetoothCharacteristicListener, LoginListener, DialogInterface.OnDismissListener, PlaysetConnectionListener
    {
      ...
    }
    

    继承AppCompatActivity,可以说是新版的Activity(support v7中更新的),主要继承的借口有
    BluetoothCharacteristicListener

    
    public abstract interface BluetoothCharacteristicListener
    {
      public abstract void bleAvailableServices();
      public abstract void bleBatteryLevel(String paramString);
      public abstract void bleConnectedPlayset();
      public abstract void bleDisconnectedPlayset();
      public abstract void bleFirmwareUpdateStatus(int paramInt);
      public abstract void bleLcdsStates(byte[] paramArrayOfByte);
      public abstract void bleLettersFromPlayset(String paramString, byte[] paramArrayOfByte);
      public abstract void blePlaysetFirmwareRevision(String paramString);
      public abstract void blePlaysetHardwareRevision(String paramString);
      public abstract void blePlaysetManufacturerName(String paramString);
      public abstract void blePlaysetModelNumber(String paramString);
      public abstract void blePlaysetName(String paramString);
    }
    

    LoginListener

    
    public abstract interface LoginListener
    {
      public abstract void didFinishSdkUserConfiguration();
      public abstract void didSelectedChild(Player paramPlayer);
    }
    

    Player就是包含用户多种属性的序列化类

    
      @SerializedName("activityDate")
      private String activityDate;
      @SerializedName("avatar")
      private String avatar;
      @SerializedName("createdAt")
      private String createdAt;
      @SerializedName("currentLevel")
      private String currentLevel;
      @SerializedName("dateofBirth")
      private String dateofBirth;
      @SerializedName("firstName")
      private String firstName;
      @SerializedName("game")
      private String game;
      @SerializedName("gender")
      private String gender;
      @SerializedName("id")
      private String id;
      @SerializedName("imgbase64")
      private String imgbase64;
      @SerializedName("owner")
      private String owner;
      @SerializedName("profileURL")
      private String profileURL;
      @SerializedName("status")
      private String status;
      @SerializedName("updatedAt")
      private String updatedAt;
    

    PlaysetConnectionListener

    
    public abstract interface PlaysetConnectionListener
    {
      public abstract void availableServices();
      public abstract void batteryLevel(String paramString);
      public abstract void connectedPlayset();
      public abstract void didClearTheCharctersOnBoard();
      public abstract void disconnectedPlayset();
      public abstract void firmwareUpdateStatus(int paramInt);
      public abstract void gamePaused(boolean paramBoolean);
      public abstract void lcdsStates(byte[] paramArrayOfByte);
      public abstract void lettersFromPlayset(String paramString, byte[] paramArrayOfByte);
      public abstract void playsetFirmwareRevision(String paramString);
      public abstract void playsetHardwareRevision(String paramString);
      public abstract void playsetManufacturerName(String paramString);
      public abstract void playsetModelNumber(String paramString);
      public abstract void playsetName(String paramString);
    }
    

    下面我们重点看BluetoothBaseActivity的类实现,这个对我们理解所有的工作流程有非常的帮助!

    成员变量

    
      // 用户Connection监听器
      private static PlaysetConnectionListener playsetConnectionListener;
      // 是否锁屏
      private boolean isScreenLocked = true;
      private View mDecorView;
      private ProgressDialog progressDialog;
      // 本地存储
      private SharedPrefUtil sharedPrefUtil;
    

    关键成员函数

      onCreate
    
      protected void onCreate(Bundle paramBundle)
      {
        requestWindowFeature(1);
        super.onCreate(paramBundle);
        getWindow().setFlags(1024, 1024);
        mDecorView = getWindow().getDecorView();
        hideSystemUI();
        Util.IS_APP_RUNNING = true;
        // 蓝牙初始化,有关BluetoothUtil我们之后说
        if (!BluetoothUtil.isInitialized()) {
          BluetoothUtil.initialize(getApplicationContext());
        }
        // 设置蓝牙监听器
        BluetoothUtil.setListener(this);
        // 设置本地存储
        sharedPrefUtil = new SharedPrefUtil(this);
        if (progressDialog == null)
        {
          progressDialog = new ProgressDialog(this, R.style.SPProgressDialogTheme);
          progressDialog.setOnDismissListener(this);
        }
        // 未设置分辨率,设置分辨率,用于屏幕适配
        if (Constants.getDeviceWidth() == 0) {
          SPSplashScreenActivity.getDeviceDimensions(this);
        }
        new Handler().postDelayed(new Runnable()
        {
          public void run()
          {
            // 配置UI
            ViewGroup localViewGroup = (ViewGroup)((ViewGroup)findViewById(16908290)).getChildAt(0);
            BluetoothBaseActivity.this.setupUI(localViewGroup);
          }
        }, 1000L);
      }
    
      onResume

    Android生命周期图如下:

    
      protected void onResume()
      {
        super.onResume();
        // 设置监听器
        BluetoothUtil.setListener(this);
        ...
        // 下面这里非常非常重要!!!
        try
        {
    
          Class localClass = Class.forName(getString(R.string.game_activity));
          if (getClass().equals(localClass))
          {
            LoginActivity.setListener(this);
            ManagePlayerActivity.setListener(this);
            setplaysetConnectionListener(this);
          }
          ...
          return;
        }
        catch (Exception localException)
        {
          ...
        }
      }
    

    我们需要分析上面这段内容

    getString:获得定义的字符串在res/string.xml中。满足当前运行类是指定game_activity时,配置监听器!

      LoginListener中接口的实现
    
    // 空实现
    public void didFinishSdkUserConfiguration() {}
    public void didSelectedChild(Player paramPlayer) {}
    
      PlaysetConnectionListener中接口的实现
    
    // 空实现
    public void availableServices() {}
    public void didClearTheCharctersOnBoard() {}
    
      BluetoothCharacteristicListener中接口的实现
    
      public void bleAvailableServices()
      {
        if (playsetConnectionListener != null) {
          playsetConnectionListener.availableServices();
        }
      }
      
      // 获取电量等级
      public void bleBatteryLevel(String paramString)
      {
        if (playsetConnectionListener != null) {
          playsetConnectionListener.batteryLevel(paramString);
        }
        int i = Util.parseInt(paramString);
        if (i < 10)
        {
          String str1 = getString(R.string.Oops);
          String str2 = getString(R.string.LowBatteryMsg);
          if (i == 0) {
            paramString = "1";
          }
          Util.showAlert(this, str1, str2.replace("X", paramString), getString(R.string.Ok), null);
        }
      }
      //
      public void bleConnectedPlayset()
      {
        if (playsetConnectionListener != null) {
          playsetConnectionListener.connectedPlayset();
        }
      }
      //
      public void bleDisconnectedPlayset()
      {
        if (playsetConnectionListener != null) {
          playsetConnectionListener.disconnectedPlayset();
        }
        if (...)
        {
          ...
          try
          {
            ...
            PlayerUtil.startPlaysetScanActivity(this);
            return;
          }
          catch (ClassNotFoundException localClassNotFoundException)
          {
            localClassNotFoundException.printStackTrace();
          }
        }
      }
    
      // 
      public void bleFirmwareUpdateStatus(int paramInt)
      {
        if (playsetConnectionListener != null) {
          playsetConnectionListener.firmwareUpdateStatus(paramInt);
        }
      }
      
      public void bleLcdsStates(byte[] paramArrayOfByte)
      {
        if (playsetConnectionListener != null) {
          playsetConnectionListener.lcdsStates(paramArrayOfByte);
        }
      }
    
      public void bleLettersFromPlayset(String paramString, byte[] paramArrayOfByte)
      {
        if (playsetConnectionListener != null)
        {
          playsetConnectionListener.lettersFromPlayset(paramString, paramArrayOfByte);
          if (paramString.trim().length() == 0) {
            playsetConnectionListener.didClearTheCharctersOnBoard();
          }
        }
      }
    
      public void blePlaysetFirmwareRevision(String paramString)
      {
        if (playsetConnectionListener != null) {
          playsetConnectionListener.playsetFirmwareRevision(paramString);
        }
        sharedPrefUtil.setString("FIRMWARE_RIVISION", paramString);
      }
    
      public void blePlaysetHardwareRevision(String paramString)
      {
        if (playsetConnectionListener != null) {
          playsetConnectionListener.playsetHardwareRevision(paramString);
        }
        sharedPrefUtil.setString("HARDWARE_RIVISION", paramString);
      }
    
      public void blePlaysetManufacturerName(String paramString)
      {
        if (playsetConnectionListener != null) {
          playsetConnectionListener.playsetManufacturerName(paramString);
        }
        sharedPrefUtil.setString("PLAYSET_MANUFACTURER", paramString);
      }
    
      public void blePlaysetModelNumber(String paramString)
      {
        if (playsetConnectionListener != null) {
          playsetConnectionListener.playsetModelNumber(paramString);
        }
        sharedPrefUtil.setString("PLAYSET_MODEL", paramString);
      }
    
      public void blePlaysetName(String paramString)
      {
        if (playsetConnectionListener != null) {
          playsetConnectionListener.playsetName(paramString);
        }
      }
    

    至此我们分析了BluetoothBaseActivity,下一节我们主要分析ManagePlayerActivity

    Android基础知识

    1 有关3G/4G技术
    3G:速率一般在几百Kbps,较之前的2G和2.5G在数据传输速度上有很大提升。
    4G:速度可达到100Mbps以上,几乎可以满足人们的所有传输数据的需求。
    3G技术标准:
    WCDMA:全球80%以上的3G网络都是采用此种制式。中国联通运营。
    CDMA2000:目前日韩及北美使用较多。中国电信运营。
    TD-SCDMA:中国自主知识产权的3G通信技术。中国移动运营。

    2 搭建环境
    2.1. 所需资源
    JDK,Java开发环境。下载地址:http://www.oracle.com
    Eclipse,IBM公司开发的一款开源IDE。http://www.eclipse.org
    Android SDK,Android 开发工具,包含开发Android程序所需类库、源码、文档、案例等资源。http://www.android.com
    ADT插件,ADT 是 Eclipse 平台下用来开发 Android 应用程序的插件。http://www.android.com
    3 常用命令行
    列出可以使用的Android
    android list targets
    列出可以使用的虚拟机
    android list avd
    创建虚拟机
    emulator –avd <虚拟机名>
    显示已连接的设备
    adb devices
    导入文件到手机
    adb push <Windows源文件路径> <手机目标路径>
    从手机导出文件
    adb pull <手机源文件路径> <Windows目录路径>
    安装程序
    adb install <apk文件路径>
    卸载程序
    adb uninstall <包名>
    重启adb
    adb kill-server
    abd start-server
    4 创建与代码结构
    src:源代码
    gen:系统自动生成的文件
    java 中记录了项目中各种资源ID
    res:系统资源,所有文件都会在R文件生成资源ID
    drawable:图片
    layout:界面布局
    values:数据
    anim:定义动画的XML
    raw:原生文件
    assets:资源路径,不会在R文件注册
    project.properties:供Eclipse使用,读取该项目使用Android版本号。早期版本名为:default.properties
    AndroidManifest.xml:清单文件,在软件安装的时候被读取Android中的四大组件(Activity、ContentProvider、BroadcastReceiver、Service)都需要在该文件中注册,程序所需的权限也需要在此文件中声明,例如:电话、短信、互联网、访问SD卡。
    bin:二进制文件,包括class、资源文件、dex、apk等
    proguard.cfg:用来混淆代码的配置文件,防止别人反编译。
    5 程序启动过程
    Eclipse将.java源文件编译成.class;使用dx工具将所有.class文件转换为.dex文件;再将.dex文件和所有资源打包成.apk文件;将.apk文件安装到虚拟机完成程序安装;启动程序 – 开启进程 – 开启主线程;创建Activity对象 – 执行OnCreate()方法;按照main.xml文件初始化界面。
    6 查看程序错误
    Android程序中如果出错,错误不会显示在Console中,而是显示在LogCat界面下。可以从window – show view中打开;日志信息分为5个级别:verbose > debug > info > warn > error 高级的包含低级的;可以创建过滤器对日志进行过滤显示,点击绿色加号,可以按照tag、pid、level进行筛选。
    7 短信发送
    搭建界面需要组件:TextView、EditText、Button;给Button添加监听器,当被点击的时候获取号码,获取内容;使用SmsManager发送短信;需要注册短信发送权限
    8 布局
    RelativeLayout(相对布局):android-sdk-windows/docs/guide/topics/ui/layout-objects.html#relativelayout
    FrameLayout(帧布局):android-sdk-windows/docs/guide/topics/ui/layout-objects.html#framelayout
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);