initial version
This commit is contained in:
commit
a0d3e184f9
18 changed files with 1547 additions and 0 deletions
1
app/.gitignore
vendored
Normal file
1
app/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
32
app/build.gradle
Normal file
32
app/build.gradle
Normal file
|
@ -0,0 +1,32 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 24
|
||||
buildToolsVersion "25.0.0"
|
||||
defaultConfig {
|
||||
applicationId "xyz.hoyer.iconsole"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 24
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
})
|
||||
compile 'com.android.support:appcompat-v7:24.2.1'
|
||||
compile 'com.android.support:support-v4:24.2.1'
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
provided project(':android_antlib_4-14-0')
|
||||
}
|
25
app/proguard-rules.pro
vendored
Normal file
25
app/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /home/harald/Android/Sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
25
app/src/main/AndroidManifest.xml
Normal file
25
app/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="xyz.hoyer.iconsole">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".ChannelList"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/FullscreenTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<service android:name=".ChannelService"></service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
40
app/src/main/java/com/dsi/ant/channel/PredefinedNetwork.java
Normal file
40
app/src/main/java/com/dsi/ant/channel/PredefinedNetwork.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
package com.dsi.ant.channel;
|
||||
|
||||
/**
|
||||
* Created by harald on 24.04.17.
|
||||
*/
|
||||
|
||||
public enum PredefinedNetwork {
|
||||
INVALID(-1),
|
||||
PUBLIC(0),
|
||||
ANT_PLUS1(1), //
|
||||
ANT_FS(2);
|
||||
|
||||
private final int mRawValue;
|
||||
private static final PredefinedNetwork[] sValues = values();
|
||||
|
||||
private PredefinedNetwork(int rawValue) {
|
||||
this.mRawValue = rawValue;
|
||||
}
|
||||
|
||||
int getRawValue() {
|
||||
return this.mRawValue;
|
||||
}
|
||||
|
||||
private boolean equals(int rawValue) {
|
||||
return rawValue == this.mRawValue;
|
||||
}
|
||||
|
||||
static PredefinedNetwork create(int rawValue) {
|
||||
PredefinedNetwork code = INVALID;
|
||||
|
||||
for(int i = 0; i < sValues.length; ++i) {
|
||||
if(sValues[i].equals(rawValue)) {
|
||||
code = sValues[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
}
|
296
app/src/main/java/xyz/hoyer/iconsole/ChannelController.java
Normal file
296
app/src/main/java/xyz/hoyer/iconsole/ChannelController.java
Normal file
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
* Copyright 2012 Dynastream Innovations Inc.
|
||||
*
|
||||
* 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 xyz.hoyer.iconsole;
|
||||
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.dsi.ant.channel.AntChannel;
|
||||
import com.dsi.ant.channel.AntCommandFailedException;
|
||||
import com.dsi.ant.channel.IAntChannelEventHandler;
|
||||
import com.dsi.ant.message.ChannelId;
|
||||
import com.dsi.ant.message.ChannelType;
|
||||
import com.dsi.ant.message.fromant.AcknowledgedDataMessage;
|
||||
import com.dsi.ant.message.fromant.BroadcastDataMessage;
|
||||
import com.dsi.ant.message.fromant.ChannelEventMessage;
|
||||
import com.dsi.ant.message.fromant.MessageFromAntType;
|
||||
import com.dsi.ant.message.ipc.AntMessageParcel;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class ChannelController
|
||||
{
|
||||
// The device type and transmission type to be part of the channel ID message
|
||||
private static final int CHANNEL_PROOF_DEVICE_TYPE = 0x08;
|
||||
private static final int CHANNEL_PROOF_TRANSMISSION_TYPE = 1;
|
||||
|
||||
// The period and frequency values the channel will be configured to
|
||||
private static final int CHANNEL_PROOF_PERIOD = 32768; // 1 Hz
|
||||
private static final int CHANNEL_PROOF_FREQUENCY = 77;
|
||||
|
||||
private static final String TAG = ChannelController.class.getSimpleName();
|
||||
|
||||
private static Random randGen = new Random();
|
||||
|
||||
private AntChannel mAntChannel;
|
||||
private ChannelBroadcastListener mChannelBroadcastListener;
|
||||
|
||||
private ChannelEventCallback mChannelEventCallback = new ChannelEventCallback();
|
||||
|
||||
private ChannelInfo mChannelInfo;
|
||||
|
||||
private boolean mIsOpen;
|
||||
|
||||
static public abstract class ChannelBroadcastListener
|
||||
{
|
||||
public abstract void onBroadcastChanged(ChannelInfo newInfo);
|
||||
}
|
||||
|
||||
public ChannelController(AntChannel antChannel, boolean isMaster, int deviceId,
|
||||
ChannelBroadcastListener broadcastListener)
|
||||
{
|
||||
mAntChannel = antChannel;
|
||||
mChannelInfo = new ChannelInfo(deviceId, isMaster, randGen.nextInt(256));
|
||||
mChannelBroadcastListener = broadcastListener;
|
||||
|
||||
openChannel();
|
||||
}
|
||||
|
||||
|
||||
boolean openChannel()
|
||||
{
|
||||
if(null != mAntChannel)
|
||||
{
|
||||
if(mIsOpen)
|
||||
{
|
||||
Log.w(TAG, "Channel was already open");
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Although this reference code sets ChannelType to either a transmitting master or a receiving slave,
|
||||
* the standard for ANT is that channels communication is bidirectional. The use of single-direction
|
||||
* communication in this app is for ease of understanding as reference code. For more information and
|
||||
* any additional features on ANT channel communication, refer to the ANT Protocol Doc found at:
|
||||
* http://www.thisisant.com/resources/ant-message-protocol-and-usage/
|
||||
*/
|
||||
ChannelType channelType = (mChannelInfo.isMaster ?
|
||||
ChannelType.BIDIRECTIONAL_MASTER : ChannelType.BIDIRECTIONAL_SLAVE);
|
||||
|
||||
// Channel ID message contains device number, type and transmission type. In
|
||||
// order for master (TX) channels and slave (RX) channels to connect, they
|
||||
// must have the same channel ID, or wildcard (0) is used.
|
||||
ChannelId channelId = new ChannelId(mChannelInfo.deviceNumber,
|
||||
CHANNEL_PROOF_DEVICE_TYPE, CHANNEL_PROOF_TRANSMISSION_TYPE);
|
||||
|
||||
try
|
||||
{
|
||||
// Setting the channel event handler so that we can receive messages from ANT
|
||||
mAntChannel.setChannelEventHandler(mChannelEventCallback);
|
||||
|
||||
// Performs channel assignment by assigning the type to the channel. Additional
|
||||
// features (such as, background scanning and frequency agility) can be enabled
|
||||
// by passing an ExtendedAssignment object to assign(ChannelType, ExtendedAssignment).
|
||||
mAntChannel.assign(channelType);
|
||||
|
||||
/*
|
||||
* Configures the channel ID, messaging period and rf frequency after assigning,
|
||||
* then opening the channel.
|
||||
*
|
||||
* For any additional ANT features such as proximity search or background scanning, refer to
|
||||
* the ANT Protocol Doc found at:
|
||||
* http://www.thisisant.com/resources/ant-message-protocol-and-usage/
|
||||
*/
|
||||
mAntChannel.setChannelId(channelId);
|
||||
mAntChannel.setPeriod(CHANNEL_PROOF_PERIOD);
|
||||
mAntChannel.setRfFrequency(CHANNEL_PROOF_FREQUENCY);
|
||||
mAntChannel.open();
|
||||
mIsOpen = true;
|
||||
|
||||
Log.d(TAG, "Opened channel with device number: " + mChannelInfo.deviceNumber);
|
||||
} catch (RemoteException e) {
|
||||
channelError(e);
|
||||
} catch (AntCommandFailedException e) {
|
||||
// This will release, and therefore unassign if required
|
||||
channelError("Open failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.w(TAG, "No channel available");
|
||||
}
|
||||
|
||||
return mIsOpen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the Channel Event Handler Interface so that messages can be
|
||||
* received and channel death events can be handled.
|
||||
*/
|
||||
public class ChannelEventCallback implements IAntChannelEventHandler
|
||||
{
|
||||
private void updateData(byte[] data) {
|
||||
mChannelInfo.broadcastData = data;
|
||||
|
||||
mChannelBroadcastListener.onBroadcastChanged(mChannelInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChannelDeath()
|
||||
{
|
||||
// Display channel death message when channel dies
|
||||
displayChannelError("Channel Death");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveMessage(MessageFromAntType messageType, AntMessageParcel antParcel) {
|
||||
Log.d(TAG, "Rx: "+ antParcel);
|
||||
|
||||
// Switching on message type to handle different types of messages
|
||||
switch(messageType)
|
||||
{
|
||||
// If data message, construct from parcel and update channel data
|
||||
case BROADCAST_DATA:
|
||||
// Rx Data
|
||||
updateData(new BroadcastDataMessage(antParcel).getPayload());
|
||||
break;
|
||||
case ACKNOWLEDGED_DATA:
|
||||
// Rx Data
|
||||
updateData(new AcknowledgedDataMessage(antParcel).getPayload());
|
||||
break;
|
||||
case CHANNEL_EVENT:
|
||||
// Constructing channel event message from parcel
|
||||
ChannelEventMessage eventMessage = new ChannelEventMessage(antParcel);
|
||||
|
||||
// Switching on event code to handle the different types of channel events
|
||||
switch(eventMessage.getEventCode())
|
||||
{
|
||||
case TX:
|
||||
// Use old info as this is what remote device has just received
|
||||
mChannelBroadcastListener.onBroadcastChanged(mChannelInfo);
|
||||
|
||||
mChannelInfo.broadcastData[0]++;
|
||||
|
||||
if(mIsOpen)
|
||||
{
|
||||
try {
|
||||
// Setting the data to be broadcast on the next channel period
|
||||
mAntChannel.setBroadcastData(mChannelInfo.broadcastData);
|
||||
} catch (RemoteException e) {
|
||||
channelError(e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RX_SEARCH_TIMEOUT:
|
||||
// TODO May want to keep searching
|
||||
displayChannelError("No Device Found");
|
||||
break;
|
||||
case CHANNEL_CLOSED:
|
||||
case CHANNEL_COLLISION:
|
||||
case RX_FAIL:
|
||||
case RX_FAIL_GO_TO_SEARCH:
|
||||
case TRANSFER_RX_FAILED:
|
||||
case TRANSFER_TX_COMPLETED:
|
||||
case TRANSFER_TX_FAILED:
|
||||
case TRANSFER_TX_START:
|
||||
case UNKNOWN:
|
||||
// TODO More complex communication will need to handle these events
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ANT_VERSION:
|
||||
case BURST_TRANSFER_DATA:
|
||||
case CAPABILITIES:
|
||||
case CHANNEL_ID:
|
||||
case CHANNEL_RESPONSE:
|
||||
case CHANNEL_STATUS:
|
||||
case SERIAL_NUMBER:
|
||||
case OTHER:
|
||||
// TODO More complex communication will need to handle these message types
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelInfo getCurrentInfo()
|
||||
{
|
||||
return mChannelInfo;
|
||||
}
|
||||
|
||||
void displayChannelError(String displayText)
|
||||
{
|
||||
mChannelInfo.die(displayText);
|
||||
mChannelBroadcastListener.onBroadcastChanged(mChannelInfo);
|
||||
}
|
||||
|
||||
void channelError(RemoteException e) {
|
||||
String logString = "Remote service communication failed.";
|
||||
|
||||
Log.e(TAG, logString);
|
||||
|
||||
displayChannelError(logString);
|
||||
}
|
||||
|
||||
void channelError(String error, AntCommandFailedException e) {
|
||||
StringBuilder logString;
|
||||
|
||||
if(e.getResponseMessage() != null) {
|
||||
String initiatingMessageId = "0x"+ Integer.toHexString(
|
||||
e.getResponseMessage().getInitiatingMessageId());
|
||||
String rawResponseCode = "0x"+ Integer.toHexString(
|
||||
e.getResponseMessage().getRawResponseCode());
|
||||
|
||||
logString = new StringBuilder(error)
|
||||
.append(". Command ")
|
||||
.append(initiatingMessageId)
|
||||
.append(" failed with code ")
|
||||
.append(rawResponseCode);
|
||||
} else {
|
||||
String attemptedMessageId = "0x"+ Integer.toHexString(
|
||||
e.getAttemptedMessageType().getMessageId());
|
||||
String failureReason = e.getFailureReason().toString();
|
||||
|
||||
logString = new StringBuilder(error)
|
||||
.append(". Command ")
|
||||
.append(attemptedMessageId)
|
||||
.append(" failed with reason ")
|
||||
.append(failureReason);
|
||||
}
|
||||
|
||||
Log.e(TAG, logString.toString());
|
||||
|
||||
mAntChannel.release();
|
||||
|
||||
displayChannelError("ANT Command Failed");
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
// TODO kill all our resources
|
||||
if (null != mAntChannel)
|
||||
{
|
||||
mIsOpen = false;
|
||||
|
||||
// Releasing the channel to make it available for others.
|
||||
// After releasing, the AntChannel instance cannot be reused.
|
||||
mAntChannel.release();
|
||||
mAntChannel = null;
|
||||
}
|
||||
|
||||
displayChannelError("Channel Closed");
|
||||
}
|
||||
}
|
54
app/src/main/java/xyz/hoyer/iconsole/ChannelInfo.java
Normal file
54
app/src/main/java/xyz/hoyer/iconsole/ChannelInfo.java
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2012 Dynastream Innovations Inc.
|
||||
*
|
||||
* 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 xyz.hoyer.iconsole;
|
||||
|
||||
import com.dsi.ant.message.fromant.DataMessage;
|
||||
|
||||
public class ChannelInfo
|
||||
{
|
||||
public final int deviceNumber;
|
||||
|
||||
/** Master / Slave */
|
||||
public final boolean isMaster;
|
||||
|
||||
public byte[] broadcastData = new byte[DataMessage.LENGTH_STANDARD_PAYLOAD];
|
||||
|
||||
public boolean error;
|
||||
private String mErrorMessage;
|
||||
|
||||
public ChannelInfo(int deviceNumber, boolean isMaster, int initialBroadcastValue)
|
||||
{
|
||||
this.deviceNumber = deviceNumber;
|
||||
this.isMaster = isMaster;
|
||||
|
||||
// Not actually concerned with this value, so can cast to byte and lose data without issues
|
||||
broadcastData[0] = (byte)initialBroadcastValue;
|
||||
|
||||
error = false;
|
||||
mErrorMessage = null;
|
||||
}
|
||||
|
||||
public void die(String errorMessage)
|
||||
{
|
||||
error = true;
|
||||
mErrorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public String getErrorString()
|
||||
{
|
||||
return mErrorMessage;
|
||||
}
|
||||
}
|
387
app/src/main/java/xyz/hoyer/iconsole/ChannelList.java
Normal file
387
app/src/main/java/xyz/hoyer/iconsole/ChannelList.java
Normal file
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
* Copyright 2012 Dynastream Innovations Inc.
|
||||
*
|
||||
* 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 xyz.hoyer.iconsole;
|
||||
|
||||
import com.dsi.ant.channel.ChannelNotAvailableException;
|
||||
import xyz.hoyer.iconsole.ChannelService.ChannelChangedListener;
|
||||
import xyz.hoyer.iconsole.ChannelService.ChannelServiceComm;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ToggleButton;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ChannelList extends Activity {
|
||||
private static final String TAG = ChannelList.class.getSimpleName();
|
||||
|
||||
private final String PREF_TX_BUTTON_CHECKED_KEY = "ChannelList.TX_BUTTON_CHECKED";
|
||||
private boolean mCreateChannelAsMaster;
|
||||
|
||||
private ChannelServiceComm mChannelService;
|
||||
|
||||
private ArrayList<String> mChannelDisplayList = new ArrayList<String>();
|
||||
private ArrayAdapter<String> mChannelListAdapter;
|
||||
private SparseArray<Integer> mIdChannelListIndexMap = new SparseArray<Integer>();
|
||||
|
||||
private boolean mChannelServiceBound = false;
|
||||
|
||||
private void initButtons()
|
||||
{
|
||||
Log.v(TAG, "initButtons...");
|
||||
|
||||
//Register Master/Slave Toggle handler
|
||||
ToggleButton toggleButton_MasterSlave = (ToggleButton)findViewById(R.id.toggleButton_MasterSlave);
|
||||
toggleButton_MasterSlave.setEnabled(mChannelServiceBound);
|
||||
toggleButton_MasterSlave.setChecked(mCreateChannelAsMaster);
|
||||
toggleButton_MasterSlave.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton arg0, boolean enabled)
|
||||
{
|
||||
mCreateChannelAsMaster = enabled;
|
||||
}
|
||||
});
|
||||
|
||||
//Register Add Channel Button handler
|
||||
Button button_addChannel = (Button)findViewById(R.id.button_AddChannel);
|
||||
button_addChannel.setEnabled(mChannelServiceBound);
|
||||
button_addChannel.setOnClickListener(new OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
addNewChannel(mCreateChannelAsMaster);
|
||||
}
|
||||
});
|
||||
|
||||
//Register Clear Channels Button handler
|
||||
Button button_clearChannels = (Button)findViewById(R.id.button_ClearChannels);
|
||||
button_clearChannels.setEnabled(mChannelServiceBound);
|
||||
button_clearChannels.setOnClickListener(new OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
clearAllChannels();
|
||||
}
|
||||
});
|
||||
|
||||
Log.v(TAG, "...initButtons");
|
||||
}
|
||||
|
||||
private void initPrefs()
|
||||
{
|
||||
Log.v(TAG, "initPrefs...");
|
||||
|
||||
// Retrieves the app's current state of channel transmission mode
|
||||
// from preferences to handle app resuming.
|
||||
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
|
||||
|
||||
mCreateChannelAsMaster = preferences.getBoolean(PREF_TX_BUTTON_CHECKED_KEY, true);
|
||||
|
||||
Log.v(TAG, "...initPrefs");
|
||||
}
|
||||
|
||||
private void savePrefs()
|
||||
{
|
||||
Log.v(TAG, "savePrefs...");
|
||||
|
||||
// Saves the app's current state of channel transmission mode to preferences
|
||||
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
||||
editor.putBoolean(PREF_TX_BUTTON_CHECKED_KEY, mCreateChannelAsMaster);
|
||||
|
||||
editor.commit();
|
||||
|
||||
Log.v(TAG, "...savePrefs");
|
||||
}
|
||||
|
||||
private void doBindChannelService()
|
||||
{
|
||||
Log.v(TAG, "doBindChannelService...");
|
||||
|
||||
// Binds to ChannelService. ChannelService binds and manages connection between the
|
||||
// app and the ANT Radio Service
|
||||
Intent bindIntent = new Intent(this, ChannelService.class);
|
||||
startService(bindIntent);
|
||||
mChannelServiceBound = bindService(bindIntent, mChannelServiceConnection, Context.BIND_AUTO_CREATE);
|
||||
|
||||
if(!mChannelServiceBound) //If the bind returns false, run the unbind method to update the GUI
|
||||
doUnbindChannelService();
|
||||
|
||||
Log.i(TAG, " Channel Service binding = "+ mChannelServiceBound);
|
||||
|
||||
Log.v(TAG, "...doBindChannelService");
|
||||
}
|
||||
|
||||
private void doUnbindChannelService()
|
||||
{
|
||||
Log.v(TAG, "doUnbindChannelService...");
|
||||
|
||||
if(mChannelServiceBound)
|
||||
{
|
||||
unbindService(mChannelServiceConnection);
|
||||
|
||||
mChannelServiceBound = false;
|
||||
}
|
||||
|
||||
((Button)findViewById(R.id.button_ClearChannels)).setEnabled(false);
|
||||
((Button)findViewById(R.id.button_AddChannel)).setEnabled(false);
|
||||
((Button)findViewById(R.id.toggleButton_MasterSlave)).setEnabled(false);
|
||||
|
||||
Log.v(TAG, "...doUnbindChannelService");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Log.v(TAG, "onCreate...");
|
||||
|
||||
mChannelServiceBound = false;
|
||||
|
||||
setContentView(R.layout.activity_fullscreen);
|
||||
|
||||
initPrefs();
|
||||
|
||||
mChannelListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, mChannelDisplayList);
|
||||
ListView listView_channelList = (ListView)findViewById(R.id.listView_channelList);
|
||||
listView_channelList.setAdapter(mChannelListAdapter);
|
||||
|
||||
if(!mChannelServiceBound) doBindChannelService();
|
||||
|
||||
initButtons();
|
||||
|
||||
Log.v(TAG, "...onCreate");
|
||||
}
|
||||
|
||||
public void onBack() {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy()
|
||||
{
|
||||
Log.v(TAG, "onDestroy...");
|
||||
|
||||
doUnbindChannelService();
|
||||
|
||||
if(isFinishing())
|
||||
{
|
||||
stopService(new Intent(this, ChannelService.class));
|
||||
}
|
||||
|
||||
mChannelServiceConnection = null;
|
||||
|
||||
savePrefs();
|
||||
|
||||
Log.v(TAG, "...onDestroy");
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private ServiceConnection mChannelServiceConnection = new ServiceConnection()
|
||||
{
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder serviceBinder)
|
||||
{
|
||||
Log.v(TAG, "mChannelServiceConnection.onServiceConnected...");
|
||||
|
||||
mChannelService = (ChannelServiceComm) serviceBinder;
|
||||
|
||||
// Sets a listener that handles channel events
|
||||
mChannelService.setOnChannelChangedListener(new ChannelChangedListener()
|
||||
{
|
||||
// Occurs when a channel has new info/data
|
||||
@Override
|
||||
public void onChannelChanged(final ChannelInfo newInfo)
|
||||
{
|
||||
Integer index = mIdChannelListIndexMap.get(newInfo.deviceNumber);
|
||||
|
||||
if(null != index && index.intValue() < mChannelDisplayList.size())
|
||||
{
|
||||
mChannelDisplayList.set(index.intValue(), getDisplayText(newInfo));
|
||||
runOnUiThread(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mChannelListAdapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the UI to allow/disallow acquiring new channels
|
||||
@Override
|
||||
public void onAllowAddChannel(boolean addChannelAllowed) {
|
||||
// Enable Add Channel button and Master/Slave toggle if
|
||||
// adding channels is allowed
|
||||
((Button)findViewById(R.id.button_AddChannel)).setEnabled(addChannelAllowed);
|
||||
((Button)findViewById(R.id.toggleButton_MasterSlave)).setEnabled(addChannelAllowed);
|
||||
}
|
||||
});
|
||||
|
||||
// Initial check when connecting to ChannelService if adding channels is allowed
|
||||
boolean allowAcquireChannel = mChannelService.isAddChannelAllowed();
|
||||
((Button)findViewById(R.id.button_AddChannel)).setEnabled(allowAcquireChannel);
|
||||
((Button)findViewById(R.id.toggleButton_MasterSlave)).setEnabled(allowAcquireChannel);
|
||||
|
||||
refreshList();
|
||||
|
||||
Log.v(TAG, "...mChannelServiceConnection.onServiceConnected");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName arg0)
|
||||
{
|
||||
Log.v(TAG, "mChannelServiceConnection.onServiceDisconnected...");
|
||||
|
||||
// Clearing and disabling when disconnecting from ChannelService
|
||||
mChannelService = null;
|
||||
|
||||
((Button)findViewById(R.id.button_ClearChannels)).setEnabled(false);
|
||||
((Button)findViewById(R.id.button_AddChannel)).setEnabled(false);
|
||||
((Button)findViewById(R.id.toggleButton_MasterSlave)).setEnabled(false);
|
||||
|
||||
Log.v(TAG, "...mChannelServiceConnection.onServiceDisconnected");
|
||||
}
|
||||
};
|
||||
|
||||
// This method is called when 'Add Channel' button is clicked
|
||||
private void addNewChannel(final boolean isMaster)
|
||||
{
|
||||
Log.v(TAG, "addNewChannel...");
|
||||
|
||||
if(null != mChannelService)
|
||||
{
|
||||
ChannelInfo newChannelInfo;
|
||||
try
|
||||
{
|
||||
// Telling the ChannelService to add a new channel. This method
|
||||
// in ChannelService contains code required to acquire an ANT
|
||||
// channel from ANT Radio Service.
|
||||
newChannelInfo = mChannelService.addNewChannel(isMaster);
|
||||
} catch (ChannelNotAvailableException e)
|
||||
{
|
||||
// Occurs when a channel is not available. Printing out the
|
||||
// stack trace will show why no channels are available.
|
||||
Toast.makeText(this, "Channel Not Available", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if(null != newChannelInfo)
|
||||
{
|
||||
// Adding new channel info to the list
|
||||
addChannelToList(newChannelInfo);
|
||||
mChannelListAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Log.v(TAG, "...addNewChannel");
|
||||
}
|
||||
|
||||
private void refreshList()
|
||||
{
|
||||
Log.v(TAG, "refreshList...");
|
||||
|
||||
if(null != mChannelService)
|
||||
{
|
||||
ArrayList<ChannelInfo> chInfoList = mChannelService.getCurrentChannelInfoForAllChannels();
|
||||
|
||||
mChannelDisplayList.clear();
|
||||
for(ChannelInfo i: chInfoList)
|
||||
{
|
||||
addChannelToList(i);
|
||||
}
|
||||
mChannelListAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
Log.v(TAG, "...refreshList");
|
||||
}
|
||||
|
||||
private void addChannelToList(ChannelInfo channelInfo)
|
||||
{
|
||||
Log.v(TAG, "addChannelToList...");
|
||||
|
||||
mIdChannelListIndexMap.put(channelInfo.deviceNumber, mChannelDisplayList.size());
|
||||
mChannelDisplayList.add(getDisplayText(channelInfo));
|
||||
|
||||
Log.v(TAG, "...addChannelToList");
|
||||
}
|
||||
|
||||
|
||||
private static String getDisplayText(ChannelInfo channelInfo)
|
||||
{
|
||||
Log.v(TAG, "getDisplayText...");
|
||||
String displayText = null;
|
||||
|
||||
if(channelInfo.error)
|
||||
{
|
||||
displayText = String.format("#%-6d !:%s", channelInfo.deviceNumber, channelInfo.getErrorString());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(channelInfo.isMaster)
|
||||
{
|
||||
displayText = String.format("#%-6d Tx:[%2d]", channelInfo.deviceNumber, channelInfo.broadcastData[0] & 0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
displayText = String.format("#%-6d Rx:[%2d]", channelInfo.deviceNumber, channelInfo.broadcastData[0] & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
Log.v(TAG, "...getDisplayText");
|
||||
|
||||
return displayText;
|
||||
}
|
||||
|
||||
|
||||
private void clearAllChannels()
|
||||
{
|
||||
Log.v(TAG, "clearAllChannels...");
|
||||
|
||||
if(null != mChannelService)
|
||||
{
|
||||
// Telling ChannelService to close all the channels
|
||||
mChannelService.clearAllChannels();
|
||||
|
||||
mChannelDisplayList.clear();
|
||||
mIdChannelListIndexMap.clear();
|
||||
mChannelListAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
Log.v(TAG, "...clearAllChannels");
|
||||
}
|
||||
}
|
379
app/src/main/java/xyz/hoyer/iconsole/ChannelService.java
Normal file
379
app/src/main/java/xyz/hoyer/iconsole/ChannelService.java
Normal file
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
* Copyright 2012 Dynastream Innovations Inc.
|
||||
*
|
||||
* 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 xyz.hoyer.iconsole;
|
||||
|
||||
import xyz.hoyer.iconsole.ChannelController.ChannelBroadcastListener;
|
||||
|
||||
import com.dsi.ant.AntService;
|
||||
import com.dsi.ant.channel.AntChannel;
|
||||
import com.dsi.ant.channel.AntChannelProvider;
|
||||
import com.dsi.ant.channel.ChannelNotAvailableException;
|
||||
import com.dsi.ant.channel.PredefinedNetwork;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ChannelService extends Service
|
||||
{
|
||||
private static final String TAG = "ChannelService";
|
||||
|
||||
private Object mCreateChannel_LOCK = new Object();
|
||||
|
||||
SparseArray<ChannelController> mChannelControllerList = new SparseArray<ChannelController>();
|
||||
|
||||
ChannelChangedListener mListener;
|
||||
|
||||
int channelDeviceIdCounter = 0;
|
||||
|
||||
private boolean mAntRadioServiceBound;
|
||||
private AntService mAntRadioService = null;
|
||||
private AntChannelProvider mAntChannelProvider = null;
|
||||
private boolean mAllowAddChannel = false;
|
||||
|
||||
private ServiceConnection mAntRadioServiceConnection = new ServiceConnection()
|
||||
{
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service)
|
||||
{
|
||||
// Must pass in the received IBinder object to correctly construct an AntService object
|
||||
mAntRadioService = new AntService(service);
|
||||
|
||||
try {
|
||||
// Getting a channel provider in order to acquire channels
|
||||
mAntChannelProvider = mAntRadioService.getChannelProvider();
|
||||
|
||||
// Initial check for number of channels available
|
||||
boolean mChannelAvailable = mAntChannelProvider.getNumChannelsAvailable() > 0;
|
||||
// Initial check for if legacy interface is in use. If the
|
||||
// legacy interface is in use, applications can free the ANT
|
||||
// radio by attempting to acquire a channel.
|
||||
boolean legacyInterfaceInUse = mAntChannelProvider.isLegacyInterfaceInUse();
|
||||
|
||||
// If there are channels OR legacy interface in use, allow adding channels
|
||||
if(mChannelAvailable || legacyInterfaceInUse) {
|
||||
mAllowAddChannel = true;
|
||||
}
|
||||
else {
|
||||
// If no channels available AND legacy interface is not in use, disallow adding channels
|
||||
mAllowAddChannel = false;
|
||||
}
|
||||
|
||||
if(mAllowAddChannel) {
|
||||
if(null != mListener) {
|
||||
// Send an event that indicates if adding channels is allowed
|
||||
mListener.onAllowAddChannel(mAllowAddChannel);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (RemoteException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name)
|
||||
{
|
||||
die("Binder Died");
|
||||
|
||||
mAntChannelProvider = null;
|
||||
mAntRadioService = null;
|
||||
|
||||
if(mAllowAddChannel) { mListener.onAllowAddChannel(false); }
|
||||
mAllowAddChannel = false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public interface ChannelChangedListener
|
||||
{
|
||||
/**
|
||||
* Occurs when a Channel's Info has changed (i.e. a newly created
|
||||
* channel, channel has transmitted or received data, or if channel has
|
||||
* been closed.
|
||||
*
|
||||
* @param newInfo The channel's updated info
|
||||
*/
|
||||
void onChannelChanged(ChannelInfo newInfo);
|
||||
|
||||
/**
|
||||
* Occurs when there is adding a channel is being allowed or disallowed.
|
||||
*
|
||||
* @param addChannelAllowed True if adding channels is allowed. False, otherwise.
|
||||
*/
|
||||
void onAllowAddChannel(boolean addChannelAllowed);
|
||||
}
|
||||
|
||||
/**
|
||||
* The interface used to communicate with the ChannelService
|
||||
*/
|
||||
public class ChannelServiceComm extends Binder
|
||||
{
|
||||
/**
|
||||
* Sets the listener to be used for channel changed event callbacks.
|
||||
*
|
||||
* @param listener The listener that will receive events
|
||||
*/
|
||||
void setOnChannelChangedListener(ChannelChangedListener listener)
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current info for all channels currently added.
|
||||
*
|
||||
* @return A list that contains info for all the channels
|
||||
*/
|
||||
ArrayList<ChannelInfo> getCurrentChannelInfoForAllChannels()
|
||||
{
|
||||
ArrayList<ChannelInfo> retList = new ArrayList<ChannelInfo>();
|
||||
for(int i = 0; i < mChannelControllerList.size(); i++)
|
||||
{
|
||||
ChannelController channel = mChannelControllerList.valueAt(i);
|
||||
|
||||
retList.add(channel.getCurrentInfo());
|
||||
}
|
||||
|
||||
return retList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires and adds a channel from ANT Radio Service
|
||||
*
|
||||
* @param isMaster True if channel is transmitting, False if channel is receiving
|
||||
* @return The info for the newly acquired and added channel
|
||||
* @throws ChannelNotAvailableException
|
||||
*/
|
||||
ChannelInfo addNewChannel(final boolean isMaster) throws ChannelNotAvailableException
|
||||
{
|
||||
return createNewChannel(isMaster);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes all channels currently added.
|
||||
*/
|
||||
void clearAllChannels() { closeAllChannels(); }
|
||||
|
||||
/**
|
||||
* Queries if adding a channel is allowed.
|
||||
* @return True if adding a channel is allowed. False, otherwise.
|
||||
*/
|
||||
boolean isAddChannelAllowed() { return mAllowAddChannel; }
|
||||
}
|
||||
|
||||
private void closeAllChannels()
|
||||
{
|
||||
synchronized (mChannelControllerList)
|
||||
{
|
||||
// Closing all channels in the list
|
||||
for(int i = 0; i < mChannelControllerList.size(); i++)
|
||||
{
|
||||
mChannelControllerList.valueAt(i).close();
|
||||
}
|
||||
mChannelControllerList.clear();
|
||||
}
|
||||
|
||||
// Reset the device id counter
|
||||
channelDeviceIdCounter = 0;
|
||||
}
|
||||
|
||||
AntChannel acquireChannel() throws ChannelNotAvailableException
|
||||
{
|
||||
AntChannel mAntChannel = null;
|
||||
if(null != mAntChannelProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
/*
|
||||
* If applications require a channel with specific capabilities
|
||||
* (event buffering, background scanning etc.), a Capabilities
|
||||
* object should be created and then the specific capabilities
|
||||
* required set to true. Applications can specify both required
|
||||
* and desired Capabilities with both being passed in
|
||||
* acquireChannel(context, PredefinedNetwork,
|
||||
* requiredCapabilities, desiredCapabilities).
|
||||
*/
|
||||
mAntChannel = mAntChannelProvider.acquireChannel(this, PredefinedNetwork.ANT_PLUS1);
|
||||
/*
|
||||
NetworkKey mNK = new NetworkKey(new byte[] { (byte)0xb9, (byte)0xa5, (byte)0x21, (byte)0xfb,
|
||||
(byte)0xbd, (byte)0x72, (byte)0xc3, (byte)0x45 });
|
||||
Log.v(TAG, mNK.toString());
|
||||
mAntChannel = mAntChannelProvider.acquireChannelOnPrivateNetwork(this, mNK);
|
||||
*/
|
||||
} catch (RemoteException e)
|
||||
{
|
||||
die("ACP Remote Ex");
|
||||
}
|
||||
}
|
||||
return mAntChannel;
|
||||
}
|
||||
|
||||
public ChannelInfo createNewChannel(final boolean isMaster) throws ChannelNotAvailableException
|
||||
{
|
||||
ChannelController channelController = null;
|
||||
|
||||
synchronized(mCreateChannel_LOCK)
|
||||
{
|
||||
// Acquiring a channel from ANT Radio Service
|
||||
AntChannel antChannel = acquireChannel();
|
||||
|
||||
if(null != antChannel)
|
||||
{
|
||||
|
||||
channelDeviceIdCounter += 1;
|
||||
|
||||
// Constructing a controller that will manage and control the channel
|
||||
channelController = new ChannelController(antChannel, isMaster, channelDeviceIdCounter,
|
||||
new ChannelBroadcastListener()
|
||||
{
|
||||
@Override
|
||||
public void onBroadcastChanged(ChannelInfo newInfo)
|
||||
{
|
||||
// Sending a channel changed event when message from ANT is received
|
||||
mListener.onChannelChanged(newInfo);
|
||||
}
|
||||
});
|
||||
|
||||
mChannelControllerList.put(channelDeviceIdCounter, channelController);
|
||||
}
|
||||
}
|
||||
|
||||
if(null == channelController) return null;
|
||||
|
||||
return channelController.getCurrentInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent arg0)
|
||||
{
|
||||
return new ChannelServiceComm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives AntChannelProvider state changes being sent from ANT Radio Service
|
||||
*/
|
||||
private final BroadcastReceiver mChannelProviderStateChangedReceiver = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
if(AntChannelProvider.ACTION_CHANNEL_PROVIDER_STATE_CHANGED.equals(intent.getAction())) {
|
||||
boolean update = false;
|
||||
// Retrieving the data contained in the intent
|
||||
int numChannels = intent.getIntExtra(AntChannelProvider.NUM_CHANNELS_AVAILABLE, 0);
|
||||
boolean legacyInterfaceInUse = intent.getBooleanExtra(AntChannelProvider.LEGACY_INTERFACE_IN_USE, false);
|
||||
|
||||
if(mAllowAddChannel) {
|
||||
// Was a acquire channel allowed
|
||||
// If no channels available AND legacy interface is not in use, disallow acquiring of channels
|
||||
if(0 == numChannels && !legacyInterfaceInUse) {
|
||||
mAllowAddChannel = false;
|
||||
update = true;
|
||||
}
|
||||
} else {
|
||||
// Acquire channels not allowed
|
||||
// If there are channels OR legacy interface in use, allow acquiring of channels
|
||||
if(numChannels > 0 || legacyInterfaceInUse) {
|
||||
mAllowAddChannel = true;
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(update && (null != mListener)) {
|
||||
// AllowAddChannel has been changed, sending event callback
|
||||
mListener.onAllowAddChannel(mAllowAddChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void doBindAntRadioService()
|
||||
{
|
||||
if(BuildConfig.DEBUG) Log.v(TAG, "doBindAntRadioService");
|
||||
|
||||
// Start listing for channel available intents
|
||||
registerReceiver(mChannelProviderStateChangedReceiver, new IntentFilter(AntChannelProvider.ACTION_CHANNEL_PROVIDER_STATE_CHANGED));
|
||||
|
||||
// Creating the intent and calling context.bindService() is handled by
|
||||
// the static bindService() method in AntService
|
||||
mAntRadioServiceBound = AntService.bindService(this, mAntRadioServiceConnection);
|
||||
}
|
||||
|
||||
private void doUnbindAntRadioService()
|
||||
{
|
||||
if(BuildConfig.DEBUG) Log.v(TAG, "doUnbindAntRadioService");
|
||||
|
||||
// Stop listing for channel available intents
|
||||
try{
|
||||
unregisterReceiver(mChannelProviderStateChangedReceiver);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
if(BuildConfig.DEBUG) Log.d(TAG, "Attempting to unregister a never registered Channel Provider State Changed receiver.");
|
||||
}
|
||||
|
||||
if(mAntRadioServiceBound)
|
||||
{
|
||||
try
|
||||
{
|
||||
unbindService(mAntRadioServiceConnection);
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
// Not bound, that's what we want anyway
|
||||
}
|
||||
|
||||
mAntRadioServiceBound = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate()
|
||||
{
|
||||
super.onCreate();
|
||||
|
||||
mAntRadioServiceBound = false;
|
||||
|
||||
doBindAntRadioService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy()
|
||||
{
|
||||
closeAllChannels();
|
||||
|
||||
doUnbindAntRadioService();
|
||||
mAntChannelProvider = null;
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
static void die(String error)
|
||||
{
|
||||
Log.e(TAG, "DIE: "+ error);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue