I'm writinng Android app that receiving data via bluetooth from another device. Those data as in fact streaming non-stop. After getting about 50 or 70 of them, app slows down and stop showing me received data. App cache is full, but clearing it (deleting context.getCacheDir()) doesn't help. After restarting whole app, I can again get next part of data. WHat can I do for avoiding this "lag"?
my MainActivity:
public class MainActivity extends Activity {
private BluetoothAdapter bluetoothAdapter;
private boolean pendingRequestEnableBt = false;
private final String SAVED_PENDING_REQUEST_ENABLE_BT = "PENDING_REQUEST_ENABLE_BT";
private BluetoothResponseHandler mHandler;
private static MainActivity instance;
private DeviceConnector connector;
private TextView console;
private String deviceName;
private final int REQUEST_CONNECT_DEVICE = 1;
private final int REQUEST_ENABLE_BT = 2;
#Override
protected void onCreate(Bundle savedInstanceState) {
instance = this;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
console = (TextView) findViewById(R.id.main_text_console);
if (savedInstanceState != null) {
pendingRequestEnableBt = savedInstanceState.getBoolean(SAVED_PENDING_REQUEST_ENABLE_BT);
}
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Toast.makeText(this, "No bluetooth available", Toast.LENGTH_LONG).show();
}
if (mHandler == null) {
mHandler = new BluetoothResponseHandler(this);
} else {
mHandler.setTarget(this);
}
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
getActionBar().setSubtitle(deviceName);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVED_PENDING_REQUEST_ENABLE_BT, pendingRequestEnableBt);
outState.putString("device_name", deviceName);
if (console != null) {
final String log = console.getText().toString();
outState.putString("AC", log);
}
}
public boolean isAdapterReady() {
return (bluetoothAdapter != null) && (bluetoothAdapter.isEnabled());
}
private static class BluetoothResponseHandler extends Handler {
private WeakReference<MainActivity> mActivity;
public BluetoothResponseHandler(MainActivity activity) {
mActivity = new WeakReference<MainActivity>(activity);
}
public void setTarget(MainActivity target) {
mActivity.clear();
mActivity = new WeakReference<MainActivity>(target);
}
#Override
public void handleMessage(Message msg) {
MainActivity activity = mActivity.get();
if (activity != null) {
if (msg.what==MessageType.MESSAGE_STATE_CHANGE.getValue()) {
final ActionBar bar = activity.getActionBar();
switch (msg.arg1) {
case DeviceConnector.STATE_CONNECTED:
bar.setSubtitle("Połączono.");
break;
case DeviceConnector.STATE_CONNECTING:
bar.setSubtitle("Łączenie");
break;
case DeviceConnector.STATE_NONE:
bar.setSubtitle("Rozłączono.");
break;
}
} else if (msg.what==MessageType.MESSAGE_READ.getValue()) {
if (msg.obj != null) {
activity.appendLog((String)msg.obj);
}
} else if (msg.what==MessageType.MESSAGE_DEVICE_NAME.getValue()) {
activity.setDeviceName((String) msg.obj);
}
}
}
}
private void startDeviceListActivity() {
stopConnection();
startActivityForResult(new Intent(this, DeviceListActivity.class), REQUEST_CONNECT_DEVICE);
}
private void stopConnection() {
if (connector != null) {
connector.stop();
connector = null;
}
}
#Override
public boolean onSearchRequested() {
if (isAdapterReady()) {
startDeviceListActivity();
}
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.device_control_activity, menu);
return true;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CONNECT_DEVICE:
if (resultCode == Activity.RESULT_OK) {
String address = data.getStringExtra(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
if (isAdapterReady() && (connector == null)) setupConnector(device);
}
break;
case REQUEST_ENABLE_BT:
pendingRequestEnableBt = false;
if (resultCode != Activity.RESULT_OK) {
Toast.makeText(this, "Bt not enabled", Toast.LENGTH_LONG).show();
}
break;
}
}
private void setupConnector(BluetoothDevice connectedDevice) {
stopConnection();
connector = new DeviceConnector(new DeviceData(connectedDevice, getString(R.string.empty_device_name)), mHandler);
connector.connect();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_search:
if (isAdapterReady()) {
if (isConnected()) {
stopConnection();
} else {
startDeviceListActivity();
}
} else {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void appendLog(String message) {
String msg = message.replaceAll("[\n\t\r ]*", "");
console.append(msg.length() + ": " + msg + "\n");
final int scrollAmount = console.getLayout().getLineTop(console.getLineCount()) - console.getHeight();
console.scrollTo(0, scrollAmount>0?scrollAmount:0);
delete(getCacheDir());
}
private boolean isConnected() {
return (connector != null) && (connector.getState() == DeviceConnector.STATE_CONNECTED);
}
public static MainActivity getInstance() {
return instance;
}
public void delete(File file) {
if (file.exists()) {
if (file.isFile()) {
file.delete();
} else if (file.isDirectory()) {
for (File f:file.listFiles()) {
delete(f);
}
}
}
}
}
this code is downloaded, it isn't mine, I just modified it.
Related
I am trying to route my TTS output to an external bluetooth SCO device (works fine with local speaker and mic) but it doesn't play out.
I am setting the route for AudioManager as follows -
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);
The utterances are played out with this method -
private void say(String text, String utteranceId) {
Log.d(TAG, "Saying: " + text);
final Bundle ttsParams = new Bundle();
ttsParams.putInt(TextToSpeech.Engine.KEY_PARAM_STREAM, AudioManager.STREAM_VOICE_CALL);
mTextToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, ttsParams, utteranceId);
}
There's no audio from the speaker. If I don't setBluetoothScoOn to true it works fine with the in-built speaker.
Use this class:
public abstract class BluetoothHeadsetUtils {
private AudioManager mAudioManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothHeadset mBluetoothHeadset;
private BluetoothDevice mConnectedHeadset;
private Context mContext;
private CountDownTimer mCountDown;
private BroadcastReceiver mHeadsetBroadcastReceiver;
private BluetoothProfile.ServiceListener mHeadsetProfileListener;
private boolean mIsCountDownOn;
private boolean mIsOnHeadsetSco;
private boolean mIsStarted;
private boolean receiverRegistered;
public BluetoothHeadsetUtils(final Context context) {
mHeadsetBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
final int intExtra = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset
.STATE_DISCONNECTED);
if (intExtra == BluetoothHeadset.STATE_CONNECTED) {
BluetoothHeadsetUtils.this.mConnectedHeadset = intent.getParcelableExtra(BluetoothDevice
.EXTRA_DEVICE);
BluetoothHeadsetUtils.this.mIsCountDownOn = true;
BluetoothHeadsetUtils.this.mCountDown.start();
BluetoothHeadsetUtils.this.onHeadsetConnected();
} else if (intExtra == BluetoothHeadset.STATE_DISCONNECTED) {
if (BluetoothHeadsetUtils.this.mIsCountDownOn) {
BluetoothHeadsetUtils.this.mIsCountDownOn = false;
BluetoothHeadsetUtils.this.mCountDown.cancel();
}
BluetoothHeadsetUtils.this.mConnectedHeadset = null;
BluetoothHeadsetUtils.this.onHeadsetDisconnected();
}
} else {
final int intExtra2 = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset
.STATE_AUDIO_DISCONNECTED);
if (intExtra2 == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
BluetoothHeadsetUtils.this.mIsOnHeadsetSco = true;
if (BluetoothHeadsetUtils.this.mIsCountDownOn) {
BluetoothHeadsetUtils.this.mIsCountDownOn = false;
BluetoothHeadsetUtils.this.mCountDown.cancel();
}
BluetoothHeadsetUtils.this.onScoAudioConnected();
return;
}
if (intExtra2 == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
BluetoothHeadsetUtils.this.mIsOnHeadsetSco = false;
BluetoothHeadsetUtils.this.mBluetoothHeadset.stopVoiceRecognition(BluetoothHeadsetUtils.this
.mConnectedHeadset);
BluetoothHeadsetUtils.this.onScoAudioDisconnected();
}
}
}
};
mHeadsetProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(final int n, final BluetoothProfile bluetoothProfile) {
BluetoothHeadsetUtils.this.mBluetoothHeadset = (BluetoothHeadset) bluetoothProfile;
final List<BluetoothDevice> connectedDevices = BluetoothHeadsetUtils.this.mBluetoothHeadset
.getConnectedDevices();
if (connectedDevices.size() > 0) {
BluetoothHeadsetUtils.this.mConnectedHeadset = connectedDevices.get(0);
BluetoothHeadsetUtils.this.onHeadsetConnected();
BluetoothHeadsetUtils.this.mIsCountDownOn = true;
BluetoothHeadsetUtils.this.mCountDown.start();
} else {
BluetoothHeadsetUtils.this.noHeadsetConnected();
}
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
BluetoothHeadsetUtils.this.mContext.registerReceiver(BluetoothHeadsetUtils.this
.mHeadsetBroadcastReceiver, filter);
receiverRegistered = true;
}
public void onServiceDisconnected(final int n) {
BluetoothHeadsetUtils.this.stop();
}
};
mCountDown = new CountDownTimer(10000L, 1000L) {
public void onFinish() {
BluetoothHeadsetUtils.this.mIsCountDownOn = false;
onTimeout();
}
public void onTick(final long n) {
BluetoothHeadsetUtils.this.mBluetoothHeadset.startVoiceRecognition(BluetoothHeadsetUtils.this
.mConnectedHeadset);
}
};
mContext = context;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mAudioManager = (AudioManager) this.mContext.getSystemService(Context.AUDIO_SERVICE);
}
private boolean startBluetooth() {
return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled() && mAudioManager
.isBluetoothScoAvailableOffCall() &&
mBluetoothAdapter.getProfileProxy(mContext, mHeadsetProfileListener, BluetoothProfile.HEADSET);
}
public boolean isOnHeadsetSco() {
return mIsOnHeadsetSco;
}
protected void onTimeout() {
}
protected void noHeadsetConnected() {
}
protected void onHeadsetConnected() {
}
protected void onHeadsetDisconnected() {
}
protected void onScoAudioConnected() {
}
protected void onScoAudioDisconnected() {
}
#UiThread
public boolean start() {
if (!mIsStarted) {
mIsStarted = true;
mIsStarted = startBluetooth();
}
return mIsStarted;
}
#UiThread
public void stop() {
if (mIsStarted) {
mIsStarted = false;
stopBluetooth();
}
}
private void stopBluetooth() {
if (mIsCountDownOn) {
mIsCountDownOn = false;
mCountDown.cancel();
}
try {
if (receiverRegistered) {
mContext.unregisterReceiver(mHeadsetBroadcastReceiver);
}
} catch (IllegalArgumentException ignored) {
} finally {
receiverRegistered = false;
}
if (mBluetoothHeadset != null) {
mBluetoothHeadset.stopVoiceRecognition(mConnectedHeadset);
mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
mBluetoothHeadset = null;
}
mIsOnHeadsetSco = false;
}
}
Use your say method in the onScoAudioConnected callback.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
Error I'm getting null point exception in Bluetooth when I'm starting a service.
LiveFragment.class
public class LiveFragment extends Fragment {
// Intent request codes
private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
private static final int REQUEST_ENABLE_BT = 3;
private BluetoothAdapter mBluetoothAdapter =null;
public BluetoothChatService mChatService = null;
private PowerManager.WakeLock wakeLock = null;
private PowerManager powerManager = null;
private String mConnectedDeviceName = null;
private boolean isServiceBound;
private boolean preRequisites = true;
private SharedPreferences prefs;
private BroadcastReceiver broadcastReceiver;
private Context c;
private AbstractGatewayService ab;
protected ImageView blue_onoffBut, gps_Button, obd_inidca, ss_button, bluetooth_indicator, gps_indicator,obd_connectButt;
protected TextView ss_Status,btStatusTextView,obdStatusTextView,gpsStatusTextView;
private LinearLayout vv;
protected BluetoothSocket sock = null;
public LiveFragment() {
// Required empty public constructor
}
private final Runnable mQueueCommands = new Runnable() {
public void run() {
Log.d(TAG, "Runnable mQueueCommands ()");
if (ab != null && ab.isRunning() && ab.queueEmpty()) {
queueCommands();
}
// run again in period defined in preferences
new Handler().postDelayed(mQueueCommands, 4000);
}
};
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View view = inflater.inflate(R.layout.fragment_live, container, false);
blue_onoffBut = (ImageView) view.findViewById(R.id.blutooth_butoon);
gps_Button = (ImageView) view.findViewById(R.id.gps_button);
obd_inidca = (ImageView) view.findViewById(R.id.obd_Indicator);
ss_button = (ImageView) view.findViewById(ssButton);
gps_indicator = (ImageView) view.findViewById(R.id.gps_indicator);
bluetooth_indicator = (ImageView) view.findViewById(R.id.bluetooth_indicator);
obd_connectButt = (ImageView) view.findViewById(R.id.Obd_Connect_Button);
ss_Status = (TextView) view.findViewById(R.id.statusTx);
btStatusTextView = (TextView) view.findViewById(R.id.blue);
obdStatusTextView = (TextView) view.findViewById(R.id.obd);
gpsStatusTextView = (TextView) view.findViewById(R.id.gps);
vv = (LinearLayout) view.findViewById(R.id.fragment_live_layout);
ss_Status.setTextColor(getResources().getColor(R.color.colorGreen));
if (mBluetoothAdapter.isEnabled()) {
bluetooth_indicator.setImageResource(R.drawable.green_circle);
} else {
bluetooth_indicator.setImageResource(R.drawable.red_circle);
}
gps_Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final LocationManager manager = (LocationManager) getActivity().getSystemService( Context.LOCATION_SERVICE );
if ( !manager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
buildAlertMessageNoGps();
}
else {
showToast("Already GPS is ON");
}
}
});
blue_onoffBut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
showToast("Bluetooth Turned ON"+"\n"+"Connect Your OBD now");
bluetooth_indicator.setImageResource(R.drawable.green_circle);
mChatService = new BluetoothChatService(getActivity(), mHandler);
if (mChatService != null) {
// Only if the state is STATE_NONE, do we know that we haven't started already
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
// Start the Bluetooth chat services
mChatService.start();
}
}
} else if (mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.disable();
mBluetoothAdapter.cancelDiscovery();
obd_inidca.setImageResource(R.drawable.red_circle);
showToast("Bluetooth Turned OFF");
bluetooth_indicator.setImageResource(R.drawable.red_circle);
}
}
});
ss_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mBluetoothAdapter.isEnabled() && mChatService.getState() == BluetoothChatService.STATE_CONNECTED) {
startLiveData();
} else if (!mBluetoothAdapter.isEnabled()) {
showToast("Turn ON Bluetooth to Continue");
}
else if (!(mChatService.getState() == BluetoothChatService.STATE_CONNECTED)){
showToast("Select your OBD to Start ");
}
}
});
obd_connectButt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mBluetoothAdapter.isEnabled()) {
Intent serverIntent = new Intent(getActivity(), DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
}
else if (!mBluetoothAdapter.isEnabled()){
showToast("Turn ON Bluetooth to Connect OBD");
}
}
});
return view;
}
private ServiceConnection serviceConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder binder) {
Log.d(TAG, className.toString() + " service is bound");
isServiceBound = true;
ab = ((AbstractGatewayService.AbstractGatewayServiceBinder) binder).getService();
ab.setContext(getActivity());
Log.d(TAG, "Starting live data");
try {
ab.startService();
if (preRequisites)
btStatusTextView.setText("Connected");
} catch (IOException ioe) {
Log.e(TAG, "Failure Starting live data");
btStatusTextView.setText("Connection failed");
doUnbindService();
}
}
#Override
protected Object clone() throws CloneNotSupportedException {
Log.d(TAG, "CloneNotSupportedException ");
return super.clone();
}
#Override
public void onServiceDisconnected(ComponentName className) {
Log.d(TAG, className.toString() + " service is unbound");
isServiceBound = false;
}
};
public static String LookUpCommand(String txt) {
Log.d(TAG, "LookUpCommand() ");
for (AvailableCommandNames item : AvailableCommandNames.values()) {
if (item.getValue().equals(txt)) return item.name();
}
return txt;
}
public void updateTextView(final TextView view, final String txt) {
Log.d(TAG, "updateTextView() ");
new Handler().post(new Runnable() {
public void run() {
view.setText(txt);
}
});
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void stateUpdate(ObdCommandJob job) {
final String cmdName = job.getCommand().getName();
String cmdResult = "";
final String cmdID = LookUpCommand(cmdName);
Log.d(TAG, "stateUpdate() ");
if (job.getState().equals(ObdCommandJob.ObdCommandJobState.EXECUTION_ERROR)) {
cmdResult = job.getCommand().getResult();
if (cmdResult != null && isServiceBound) {
obdStatusTextView.setText(cmdResult.toLowerCase());
}
} else if (job.getState().equals(ObdCommandJob.ObdCommandJobState.BROKEN_PIPE)) {
if (isServiceBound)
stopLiveData();
} else if (job.getState().equals(ObdCommandJob.ObdCommandJobState.NOT_SUPPORTED)) {
cmdResult = "NA";
} else {
cmdResult = job.getCommand().getFormattedResult();
if (isServiceBound)
obdStatusTextView.setText("Receiving data...");
}
cmdResult.replace("NODATA", "0");
if (vv.findViewWithTag(cmdID) != null) {
TextView existingTV = (TextView) vv.findViewWithTag(cmdID);
existingTV.setText(cmdResult);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
if (mBluetoothAdapter == null) {
FragmentActivity activity = getActivity();
Toast.makeText(activity, "No Bluetooth Feature in Device", Toast.LENGTH_LONG).show();
activity.finish();
}
}
#Override
public void onStart() {
super.onStart();
final LocationManager manager = (LocationManager) getActivity().getSystemService( Context.LOCATION_SERVICE );
if ( !manager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
gps_indicator.setImageResource(R.drawable.red_circle);
}
if(mBluetoothAdapter.isEnabled()){
mBluetoothAdapter.disable();
bluetooth_indicator.setImageResource(R.drawable.red_circle);
}
}
#Override
public void onResume() {
super.onResume();
powerManager = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ObdReader");
final LocationManager manager = (LocationManager) getActivity().getSystemService( Context.LOCATION_SERVICE );
if ( manager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
gps_indicator.setImageResource(R.drawable.green_circle);
} else {
gps_indicator.setImageResource(R.drawable.red_circle);
}
EventBus.getDefault().register(this);
if(mBluetoothAdapter.isEnabled()) {
if (mChatService != null) {
// Only if the state is STATE_NONE, do we know that we haven't started already
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
// Start the Bluetooth chat services
mChatService.start();
}
}
}
}
#Override
public void onPause() {
super.onPause();
Log.d(TAG, "Pausing..");
releaseWakeLockIfHeld();
EventBus.getDefault().unregister(this);
}
private void showToast(String message) {
final Toast toast = Toast.makeText(getContext(), message, Toast.LENGTH_SHORT);
toast.show();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
toast.cancel();
}
}, 500);
}
#Override
public void onDestroy() {
/* unregisterReceiver(mReceiver);*/
super.onDestroy();
releaseWakeLockIfHeld();
if (mChatService != null) {
mChatService.stop();
}
if (isServiceBound) {
doUnbindService();
}
if (mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.disable();
}
showToast("Take Care!");
}
private void startLiveData() {
if (mChatService.getState() == BluetoothChatService.STATE_CONNECTED) {
Log.d(TAG, "Starting live data..");
ss_Status.setText("Stop");
ss_Status.setTextColor(getResources().getColor(R.color.colorRed));
wakeLock.acquire();
ss_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ss_Status.setText("Go Live");
ss_Status.setTextColor(getResources().getColor(R.color.colorGreen));
stopLiveData();
}
});
doBindService();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver((broadcastReceiver), new IntentFilter(OBD_GATEWAY_SERVICE));
new Handler().post(mQueueCommands);
}
}
private void stopLiveData() {
Log.d(TAG, "Stopping live data..");
releaseWakeLockIfHeld();
new Handler().removeCallbacks(mQueueCommands);
ss_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ss_Status.setText("Go Live");
ss_Status.setTextColor(getResources().getColor(R.color.colorGreen));
startLiveData();
}
});
doUnbindService();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(broadcastReceiver);
}
private void queueCommands() {
Log.d(TAG, "LiveFragment queueCommands() ");
if (isServiceBound) {
for (ObdCommand Command : ObdConfig.getCommands()) {
if (prefs.getBoolean(Command.getName(), true))
ab.queueJob(new ObdCommandJob(Command));
}
}
}
private void doBindService() {
if (!isServiceBound) {
Log.d(TAG, "Binding OBD service..");
if (preRequisites) {
btStatusTextView.setText("Connecting.....");
Intent serviceIntent = new Intent(getActivity(),ObdGatewayService.class);
getActivity().bindService(serviceIntent, serviceConn, Context.BIND_AUTO_CREATE);
}
}
}
private void doUnbindService() {
if (isServiceBound) {
if (ab.isRunning()) {
ab.stopService();
if (preRequisites)
btStatusTextView.setText("Ready...");
}
Log.d(TAG, "Unbinding OBD service..");
getActivity().unbindService(serviceConn);
isServiceBound = false;
obdStatusTextView.setText("Disconnected");
}
}
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
FragmentActivity activity = getActivity();
switch (msg.what) {
case Constants.MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BluetoothChatService.STATE_CONNECTED:
obd_inidca.setImageResource(R.drawable.green_circle);
break;
case BluetoothChatService.STATE_CONNECTING:
obd_inidca.setImageResource(R.drawable.orange_circle);
break;
case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE:
obd_inidca.setImageResource(R.drawable.red_circle);
break;
}
break;
case Constants.MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(Constants.DEVICE_NAME);
if (null != activity) {
Toast.makeText(activity, "Connected to "
+ mConnectedDeviceName, Toast.LENGTH_SHORT).show();
obd_inidca.setImageResource(R.drawable.green_circle);
}
break;
case Constants.MESSAGE_TOAST:
if (null != activity) {
Toast.makeText(activity, msg.getData().getString(Constants.TOAST),
Toast.LENGTH_SHORT).show();
}
break;
}
}
};
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CONNECT_DEVICE_SECURE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
try {
connectDevice(data, true);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void connectDevice(Intent data, boolean secure) throws IOException {
// Get the device MAC address
String address = data.getExtras()
.getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BluetoothDevice object
BluetoothDevice dev = mBluetoothAdapter.getRemoteDevice(address);
// Attempt to connect to the device
mChatService.connect(dev, secure);
}.
This is ObdGateway service class:
public class ObdGatewayService extends AbstractGatewayService {
private static final String TAG = ObdGatewayService.class.getName();
#Inject
SharedPreferences prefs;
private BluetoothDevice dev = null;
private BluetoothSocket sock = null;
private BluetoothChatService mChatservice = null;
private BluetoothAdapter bluetoothAdapter =null;
public final static String JOB_NAME_STAMP = "Name";
public final static String JOB_STATE_STAMP = "State";
public final static String JOB_RESULT_STAMP = "Result";
public final static String JOB_FORMATED_RESULT_STAMP = "Formated REsult";
public final static String OBD_GATEWAY_SERVICE = "com.samplersoft.saz.Obd.ObdGatewayService";
public void startService() throws IOException {
Log.d(TAG, "Starting service..");
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// get the remote Bluetooth device
if(mChatservice.getState() != BluetoothChatService.STATE_CONNECTED){
Toast.makeText(ctx, "No Bluetooth device selected", Toast.LENGTH_LONG).show();
// log error
Log.e(TAG, "No Bluetooth device has been selected.");
stopService();
throw new IOException();
}
else
{
Log.d(TAG, "Stopping Bluetooth discovery.");
bluetoothAdapter.cancelDiscovery();
try {
startObdConnection();
} catch (Exception e) {
Log.e(
TAG,
"There was an error while establishing connection. -> "
+ e.getMessage()
);
// in case of failure, stop this service.
stopService();
throw new IOException();
}
}
}
private void startObdConnection() throws IOException {
Log.d(TAG, "Starting OBD connection..");
isRunning = true;
if(mChatservice.getState() == BluetoothChatService.STATE_CONNECTED){
// Let's configure the connection.
Log.d(TAG, "Queueing jobs for connection configuration..");
queueJob(new ObdCommandJob(new ObdResetCommand()));
try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }
queueJob(new ObdCommandJob(new EchoOffCommand()));
queueJob(new ObdCommandJob(new EchoOffCommand()));
queueJob(new ObdCommandJob(new LineFeedOffCommand()));
queueJob(new ObdCommandJob(new TimeoutCommand(62)));
// Get protocol from preferences
queueJob(new ObdCommandJob(new SelectProtocolCommand(ObdProtocols.valueOf("AUTO"))));
// Job for returning dummy data
queueJob(new ObdCommandJob(new AmbientAirTemperatureCommand()));
queueCounter = 0L;
Log.d(TAG, "Initialization jobs queued.");
}
else {
stopService();
throw new IOException();
}
}
#Override
public void queueJob(ObdCommandJob job) {
// This is a good place to enforce the imperial units option
//job.getCommand().useImperialUnits(prefs.getBoolean(ConfigActivity.IMPERIAL_UNITS_KEY, false));
// Now we can pass it along
super.queueJob(job);
}
protected void executeQueue() throws InterruptedException {
Log.d(TAG, "Executing queue..");
while (!Thread.currentThread().isInterrupted()) {
ObdCommandJob job = null;
try {
job = jobsQueue.take();
// log job
Log.d(TAG, "Taking job[" + job.getId() + "] from queue..");
if (job.getState().equals(ObdCommandJob.ObdCommandJobState.NEW)) {
Log.d(TAG, "Job state is NEW. Run it..");
job.setState(ObdCommandJob.ObdCommandJobState.RUNNING);
if (sock.isConnected()) {
job.getCommand().run(sock.getInputStream(), sock.getOutputStream());
} else {
job.setState(ObdCommandJob.ObdCommandJobState.EXECUTION_ERROR);
Log.e(TAG, "Can't run command on a closed socket.");
}
} else
// log not new job
Log.e(TAG,
"Job state was not new, so it shouldn't be in queue. BUG ALERT!");
} catch (InterruptedException i) {
Thread.currentThread().interrupt();
} catch (UnsupportedCommandException u) {
if (job != null) {
job.setState(ObdCommandJob.ObdCommandJobState.NOT_SUPPORTED);
}
Log.d(TAG, "Command not supported. -> " + u.getMessage());
} catch (IOException io) {
if (job != null) {
if(io.getMessage().contains("Broken pipe"))
job.setState(ObdCommandJob.ObdCommandJobState.BROKEN_PIPE);
else
job.setState(ObdCommandJob.ObdCommandJobState.EXECUTION_ERROR);
}
Log.e(TAG, "IO error. -> " + io.getMessage());
} catch (Exception e) {
if (job != null) {
job.setState(ObdCommandJob.ObdCommandJobState.EXECUTION_ERROR);
}
Log.e(TAG, "Failed to run command. -> " + e.getMessage());
}
ObdCommandJob job2 = job;
if(job2 !=null)
EventBus.getDefault().post(job2);
}
}
public void stopService() {
Log.d(TAG, "Stopping service..");
jobsQueue.clear();
isRunning = false;
if (sock != null)
// close socket
try {
sock.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
// kill service
stopSelf();
}
public boolean isRunning() {
return isRunning;
}
}.
This is Abstract Class where service method gets called from from Livefragment Class from serivceConnection().
public abstract class AbstractGatewayService extends RoboService {
private static final String TAG = AbstractGatewayService.class.getName();
private final IBinder binder = new AbstractGatewayServiceBinder();
protected Context ctx;
protected boolean isRunning = false;
protected Long queueCounter = 0L;
protected BlockingQueue<ObdCommandJob> jobsQueue = new LinkedBlockingQueue<>();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
executeQueue();
} catch (InterruptedException e) {
t.interrupt();
}
}
});
protected LocalBroadcastManager broadcastManager;
#Override
public IBinder onBind(Intent intent) {
return binder;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Creating service..");
final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
t.start();
Log.d(TAG, "Service created.");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Destroying service...");
t.interrupt();
broadcastManager = LocalBroadcastManager.getInstance(this);
Log.d(TAG, "Service destroyed.");
}
public boolean isRunning() {
return isRunning;
}
public boolean queueEmpty() {
return jobsQueue.isEmpty();
}
public void queueJob(ObdCommandJob job) {
queueCounter++;
Log.d(TAG, "Adding job[" + queueCounter + "] to queue..");
job.setId(queueCounter);
try {
jobsQueue.put(job);
Log.d(TAG, "Job queued successfully.");
} catch (InterruptedException e) {
job.setState(ObdCommandJob.ObdCommandJobState.QUEUE_ERROR);
Log.e(TAG, "Failed to queue job.");
}
}
public void setContext(Context c) {
ctx = c;
}
abstract protected void executeQueue() throws InterruptedException;
abstract public void startService() throws IOException;
abstract public void stopService();
public class AbstractGatewayServiceBinder extends Binder {
public AbstractGatewayService getService() {
return AbstractGatewayService.this;
}
}
}.
You are getting the exception because in class ObdGatewayService your class member mChatservice is not the same as mChatservice in class LiveFragment
They are just different member variables
mChatservice gets assigned like this in your Fragment
mChatService = new BluetoothChatService(getActivity(), mHandler);
You need to pass this reference to ObdGatewayService 's startService() like this where ever you are instantiating/invoking it:-
ObdGatewayService ogs;
....
ogs.startservice(mChatservice); // This is fragment's member reference
And in ObdGatewayService you have to assign it accordingly:-
public void startService(BluetoothChatService _mChatservice) throws IOException {
Log.d(TAG, "Starting service..");
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mChatservice = _mChatservice //Assignment YOU ARE MISSING THIS
.......
.......
}
I am using magtek card reader audio uDynamo device and i am integrating sdk with my android application. But when i am trying to open device through openDevice() method. Application unfortunately stopped. Why its doing like this ?
This is what i am doing
m_SCRA.setConnectionType(MTConnectionType.Audio);
m_SCRA.setAddress(m_deviceAddress);
m_connectionState = MTConnectionState.Connected;
// here its stopping
m_SCRA.openDevice();
Full source code
public class MainActivity extends AppCompatActivity {
private MTSCRA m_SCRA;
private Button btn;
private TextView txt;
private TextView txt1;
private TextView msg;
private TextView msg2;
private boolean m_startTransactionActionPending;
private boolean m_turnOffLEDPending;
private EditText Edit;
private AudioManager m_audioManager;
private int m_audioVolume;
private String m_deviceAddress;
private MTConnectionType m_connectionType;
private MTConnectionState m_connectionState = MTConnectionState.Disconnected;
private Handler m_scraHandler = new Handler(new SCRAHandlerCallback());
private class SCRAHandlerCallback implements Handler.Callback {
public boolean handleMessage(Message msg)
{
try
{
android.app.AlertDialog alertDialog = new android.app.AlertDialog.Builder(MainActivity.this).create();
alertDialog.setTitle("Alert");
alertDialog.setMessage("Alert Switch");
alertDialog.setButton(android.app.AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
switch (msg.what)
{
case MTSCRAEvent.OnDeviceConnectionStateChanged:
OnDeviceStateChanged((MTConnectionState) msg.obj);
break;
case MTSCRAEvent.OnCardDataStateChanged:
OnCardDataStateChanged((MTCardDataState) msg.obj);
break;
case MTSCRAEvent.OnDataReceived:
OnCardDataReceived((IMTCardData) msg.obj);
break;
case MTSCRAEvent.OnDeviceResponse:
OnDeviceResponse((String) msg.obj);
break;
case MTEMVEvent.OnTransactionStatus:
OnTransactionStatus((byte[]) msg.obj);
break;
case MTEMVEvent.OnDisplayMessageRequest:
OnDisplayMessageRequest((byte[]) msg.obj);
break;
case MTEMVEvent.OnUserSelectionRequest:
OnUserSelectionRequest((byte[]) msg.obj);
break;
case MTEMVEvent.OnARQCReceived:
OnARQCReceived((byte[]) msg.obj);
break;
case MTEMVEvent.OnTransactionResult:
OnTransactionResult((byte[]) msg.obj);
break;
case MTEMVEvent.OnEMVCommandResult:
OnEMVCommandResult((byte[]) msg.obj);
break;
case MTEMVEvent.OnDeviceExtendedResponse:
OnDeviceExtendedResponse((String) msg.obj);
break;
}
}
catch (Exception ex)
{
}
return true;
}
}
public void OnCardDataReceived(IMTCardData cardData)
{
txt.setText(m_SCRA.getCardLast4());
}
protected void OnDeviceStateChanged(MTConnectionState deviceState)
{
setState(deviceState);
updateDisplay();
invalidateOptionsMenu();
android.app.AlertDialog alertDialog = new android.app.AlertDialog.Builder(MainActivity.this).create();
alertDialog.setTitle("Alert");
alertDialog.setMessage("Alert ondevice state");
alertDialog.setButton(android.app.AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
switch (deviceState)
{
case Disconnected:
if (m_connectionType == MTConnectionType.Audio)
{
restoreVolume();
}
break;
case Connected:
if (m_connectionType == MTConnectionType.Audio)
{
setVolumeToMax();
}
clearMessage();
clearMessage2();
break;
case Error:
sendToDisplay("[Device State Error]");
break;
case Connecting:
break;
case Disconnecting:
break;
}
}
protected void OnCardDataStateChanged(MTCardDataState cardDataState)
{
switch (cardDataState)
{
case DataNotReady:
sendToDisplay("[Card Data Not Ready]");
break;
case DataReady:
sendToDisplay("[Card Data Ready]");
break;
case DataError:
sendToDisplay("[Card Data Error]");
break;
}
}
protected void OnDeviceResponse(String data)
{
sendToDisplay("[Device Response]");
sendToDisplay(data);
if (m_startTransactionActionPending)
{
m_startTransactionActionPending = false;
startTransaction();
}
}
protected void OnTransactionStatus(byte[] data)
{
sendToDisplay("[Transaction Status]");
//sendToDisplay(TLVParser.getHexString(data));
}
protected void OnDisplayMessageRequest(byte[] data)
{
sendToDisplay("[Display Message Request]");
//String message = TLVParser.getTextString(data, 0);
//sendToDisplay(message);
//displayMessage(message);
}
protected void OnEMVCommandResult(byte[] data)
{
sendToDisplay("[EMV Command Result]");
//sendToDisplay(TLVParser.getHexString(data));
if (m_turnOffLEDPending)
{
m_turnOffLEDPending = false;
setLED(false);
}
}
protected void OnDeviceExtendedResponse(String data)
{
sendToDisplay("[Device Extended Response]");
sendToDisplay(data);
}
protected void OnUserSelectionRequest(byte[] data)
{
sendToDisplay("[User Selection Request]");
//sendToDisplay(TLVParser.getHexString(data));
//processSelectionRequest(data);
}
protected void OnARQCReceived(byte[] data)
{
sendToDisplay("[ARQC Received]");
/*sendToDisplay(TLVParser.getHexString(data));
List<HashMap<String, String>> parsedTLVList = TLVParser.parseEMVData(data, true, "");
if (parsedTLVList != null)
{
String deviceSNString = TLVParser.getTagValue(parsedTLVList, "DFDF25");
byte[] deviceSN = TLVParser.getByteArrayFromHexString(deviceSNString);
sendToDisplay("SN Bytes=" + deviceSNString);
sendToDisplay("SN String=" + TLVParser.getTextString(deviceSN, 2));
boolean approved = true;
if (mMainMenu != null)
{
approved = mMainMenu.findItem(R.id.menu_emv_approved).isChecked();
}
byte[] response = buildAcquirerResponse(deviceSN, approved);
setAcquirerResponse(response);
}*/
}
protected void OnTransactionResult(byte[] data)
{
sendToDisplay("[Transaction Result]");
//sendToDisplay(TLVParser.getHexString(data));
/*if (data != null)
{
if (data.length > 0)
{
boolean signatureRequired = (data[0] != 0);
int lenBatchData = data.length - 3;
if (lenBatchData > 0)
{
byte[] batchData = new byte[lenBatchData];
System.arraycopy(data, 3, batchData, 0, lenBatchData);
sendToDisplay("(Parsed Batch Data)");
List<HashMap<String, String>> parsedTLVList = TLVParser.parseEMVData(batchData, false, "");
displayParsedTLV(parsedTLVList);
String cidString = TLVParser.getTagValue(parsedTLVList, "9F27");
byte[] cidValue = TLVParser.getByteArrayFromHexString(cidString);
boolean approved = false;
if (cidValue != null)
{
if (cidValue.length > 0)
{
if ((cidValue[0] & (byte) 0x40) != 0)
{
approved = true;
}
}
}
if (approved)
{
if (signatureRequired)
{
displayMessage2("( Signature Required )");
}
else
{
displayMessage2("( No Signature Required )");
}
}
}
}
}
setLED(false);*/
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = ( Button) findViewById(R.id.btn);
txt = (TextView) findViewById(R.id.txt1);
txt1 = (TextView) findViewById(R.id.txt2);
msg = (TextView) findViewById(R.id.msgtext1);
msg2 = (TextView) findViewById(R.id.msgtext2);
Edit = (EditText) findViewById(R.id.editText);
//m_SCRA.setConnectionType(MTConnectionType.Audio);
//if (! m_SCRA.isDeviceConnected())
//{
// m_SCRA.openDevice();
//}
m_audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
m_SCRA = new MTSCRA(this, m_scraHandler);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
m_connectionType = MTConnectionType.Audio;
m_SCRA.setConnectionType(MTConnectionType.Audio);
m_SCRA.setAddress(m_deviceAddress);
m_connectionState = MTConnectionState.Connected;
m_SCRA.openDevice();
}
});
}
private void sendToDisplay(final String data)
{
if (data != null)
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
Edit.append(data + "\n");
}
});
}
}
private void setState(MTConnectionState deviceState)
{
m_connectionState = deviceState;
updateDisplay();
invalidateOptionsMenu();
}
private void updateDisplay()
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
if (m_connectionState == MTConnectionState.Connected)
{
updateConnectionState(R.string.connected);
}
else if (m_connectionState == MTConnectionState.Connecting)
{
updateConnectionState(R.string.connecting);
}
else if (m_connectionState == MTConnectionState.Disconnecting)
{
updateConnectionState(R.string.disconnecting);
}
else if (m_connectionState == MTConnectionState.Disconnected)
{
updateConnectionState(R.string.disconnected);
}
}
});
}
private void updateConnectionState(final int resourceId)
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
txt1.setText(resourceId);
}
});
}
private void restoreVolume()
{
setVolume(m_audioVolume);
}
private void setVolumeToMax()
{
saveVolume();
android.app.AlertDialog alertDialog = new android.app.AlertDialog.Builder(MainActivity.this).create();
alertDialog.setTitle("Alert");
alertDialog.setMessage("Alert volume max");
alertDialog.setButton(android.app.AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
int volume = m_audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
setVolume(volume);
}
private void setVolume(int volume)
{
m_audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, AudioManager.FLAG_SHOW_UI);
}
private void saveVolume()
{
m_audioVolume = m_audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
}
private void clearMessage()
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
msg.setText("");
}
});
}
private void clearMessage2()
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
msg2.setText("");
}
});
}
public void startTransaction()
{
if (m_SCRA != null)
{
byte timeLimit = 0x3C;
//byte cardType = 0x02; // Chip Only
byte cardType = 0x03; // MSR + Chip
byte option = 0x00;
byte[] amount = new byte[] {0x00, 0x00, 0x00, 0x00, 0x15, 0x00};
byte transactionType = 0x00; // Purchase
byte[] cashBack = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
byte[] currencyCode = new byte[] { 0x08, 0x40};
byte reportingOption = 0x02; // All Status Changes
clearMessage();
clearMessage2();
int result = m_SCRA.startTransaction(timeLimit, cardType, option, amount, transactionType, cashBack, currencyCode, reportingOption);
sendToDisplay("[Start Transaction] (Result=" + result + ")");
}
}
public void setLED(boolean on)
{
if (m_SCRA != null)
{
if (on)
{
m_SCRA.sendCommandToDevice(MTDeviceConstants.SCRA_DEVICE_COMMAND_STRING_SET_LED_ON);
}
else
{
m_SCRA.sendCommandToDevice(MTDeviceConstants.SCRA_DEVICE_COMMAND_STRING_SET_LED_OFF);
}
}
} }
I was facing the same issue. It turned out that I forgot audio recording runtime permission.
private void checkRecordPermission() {
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.RECORD_AUDIO},
123);
}
}
I have implemented Twilio in my android app for outgoing and incoming calls. But I'm facing an issue while getting incoming call with the background service. The issue is that I get calls in first 30-40 mins only. After sometime phone stops getting incoming calls. I tried so much. Please respond me soon. I'm sharing code with you too.
I get token from a background service which generates token after a time period.
IncomingCallService.java
public class IncomingCallService extends Service implements LoginListener,
BasicConnectionListener, BasicDeviceListener, View.OnClickListener,
CompoundButton.OnCheckedChangeListener,
RadioGroup.OnCheckedChangeListener {
private static Handler handler, handler_login;
public IncomingPhone phone;
SharedPreferences login_details;
Vibrator vibrator;
Ringtone r;
Uri notification;
public static final String LOGIN_DETAILS = "XXXXXXXX";
AudioManager am;
Intent intent;
public static String DEFAULT_CLIENT_NAME = "developer";
static String Twilio_id = "",
INCOMING_AUTH_PHP_SCRIPT = MenuItems.INCOMING_AUTH_PHP_SCRIPT
+ MenuItems.Twilio_id;
Runnable newrun;
Activity context;
Context ctx;
static String op_id = "";
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
login_details = getSharedPreferences(LOGIN_DETAILS,
Context.MODE_PRIVATE);
if (login_details.contains("twilio_Id")) {
Twilio_id = login_details.getString("twilio_Id", "");
}
handler_login = new Handler();
handler_login.postDelayed(new Runnable() {
#Override
public void run() {
Login();
handler_login.postDelayed(this, 20000);
}
}, 1000);
}
public void Login() {
phone = IncomingPhone.getInstance(getApplicationContext());
phone.setListeners(this, this, this);
phone.login(DEFAULT_CLIENT_NAME, true, true);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.intent = intent;
// I know getIntent always return NULL in service
if (intent != null) {
op_id = intent.getStringExtra("operator_id");
onCallHandler();
}
return START_STICKY;
}
public void onCallHandler() {
handler = new Handler();
newrun = new Runnable() {
#Override
public void run() {
handler.removeCallbacks(newrun);
new IncomingTokenTask().execute();
if (phone.handleIncomingIntent(intent)) {
}
handler.postDelayed(this, 2000000);
}
};
handler.postDelayed(newrun, 8000000);
}
class IncomingTokenTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... params) {
IncomingPhone.capabilityToken = EntityUtils
.toString(entity);
}
}
The BasicPhone class of twilio
public class IncomingPhone implements DeviceListener, ConnectionListener {
private static final String TAG = "IncomingPhone";
static String decodedString = "";
static String capabilityToken = "";
// TODO: change this to point to the script on your public server
private static final String AUTH_PHP_SCRIPT = MenuItems.INCOMING_AUTH_PHP_SCRIPT+MenuItems.Twilio_id;
public interface LoginListener {
public void onLoginStarted();
public void onLoginFinished();
public void onLoginError(Exception error);
}
public interface BasicConnectionListener {
public void onIncomingConnectionDisconnected();
public void onConnectionConnecting();
public void onConnectionConnected();
public void onConnectionFailedConnecting(Exception error);
public void onConnectionDisconnecting();
public void onConnectionDisconnected();
public void onConnectionFailed(Exception error);
}
public interface BasicDeviceListener {
public void onDeviceStartedListening();
public void onDeviceStoppedListening(Exception error);
}
private static IncomingPhone instance;
public static final IncomingPhone getInstance(Context context) {
if (instance == null)
instance = new IncomingPhone(context);
return instance;
}
private final Context context;
private LoginListener loginListener;
private BasicConnectionListener basicConnectionListener;
private BasicDeviceListener basicDeviceListener;
private static boolean twilioSdkInited;
private static boolean twilioSdkInitInProgress;
private boolean queuedConnect;
private Device device;
private Connection pendingIncomingConnection;
private Connection connection;
private boolean speakerEnabled;
private String lastClientName;
private boolean lastAllowOutgoing;
private boolean lastAllowIncoming;
private IncomingPhone(Context context) {
this.context = context;
}
public void setListeners(LoginListener loginListener,
BasicConnectionListener basicConnectionListener,
BasicDeviceListener basicDeviceListener) {
this.loginListener = loginListener;
this.basicConnectionListener = basicConnectionListener;
this.basicDeviceListener = basicDeviceListener;
}
private void obtainCapabilityToken(String clientName,
boolean allowOutgoing, boolean allowIncoming) {
StringBuilder url = new StringBuilder();
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
DefaultHttpClient httpclient = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory
.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(
httpclient.getParams(), registry);
#SuppressWarnings("unused")
DefaultHttpClient httpClient = new DefaultHttpClient(mgr,
httpclient.getParams());
// Set verifier
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
url.append(AUTH_PHP_SCRIPT);
// This runs asynchronously!
new GetAuthTokenAsyncTask().execute(url.toString());
}
private boolean isCapabilityTokenValid() {
if (device == null || device.getCapabilities() == null)
return false;
long expTime = (Long) device.getCapabilities().get(
Capability.EXPIRATION);
return expTime - System.currentTimeMillis() / 1000 > 0;
}
//
private void updateAudioRoute() {
AudioManager audioManager = (AudioManager) context
.getSystemService(Context.AUDIO_SERVICE);
audioManager.setSpeakerphoneOn(speakerEnabled);
}
public void login(final String clientName, final boolean allowOutgoing,
final boolean allowIncoming) {
if (loginListener != null)
loginListener.onLoginStarted();
this.lastClientName = clientName;
this.lastAllowOutgoing = allowOutgoing;
this.lastAllowIncoming = allowIncoming;
if (!twilioSdkInited) {
if (twilioSdkInitInProgress)
return;
twilioSdkInitInProgress = true;
Twilio.setLogLevel(Log.DEBUG);
Twilio.initialize(context, new Twilio.InitListener() {
#Override
public void onInitialized() {
twilioSdkInited = true;
twilioSdkInitInProgress = false;
obtainCapabilityToken(clientName, allowOutgoing,
allowIncoming);
}
#Override
public void onError(Exception error) {
twilioSdkInitInProgress = false;
if (loginListener != null)
loginListener.onLoginError(error);
}
});
} else {
obtainCapabilityToken(clientName, allowOutgoing, allowIncoming);
}
}
private void reallyLogin(final String capabilityToken) {
try {
if (device == null) {
device = Twilio.createDevice(capabilityToken, this);
Intent intent = new Intent(context, IncomingPhoneActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
device.setIncomingIntent(pendingIntent);
} else
device.updateCapabilityToken(capabilityToken);
if (loginListener != null)
loginListener.onLoginFinished();
if (queuedConnect) {
// If someone called connect() before we finished initializing
// the SDK, let's take care of that here.
connect(null);
queuedConnect = false;
}
} catch (Exception e) {
if (device != null)
device.release();
device = null;
if (loginListener != null)
loginListener.onLoginError(e);
}
}
public void setSpeakerEnabled(boolean speakerEnabled) {
if (speakerEnabled != this.speakerEnabled) {
this.speakerEnabled = speakerEnabled;
updateAudioRoute();
}
}
public void connect(Map<String, String> inParams) {
if (twilioSdkInitInProgress) {
// If someone calls connect() before the SDK is initialized, we'll
// remember
// that fact and try to connect later.
queuedConnect = true;
return;
}
if (!isCapabilityTokenValid())
login(lastClientName, lastAllowOutgoing, lastAllowIncoming);
if (device == null)
return;
if (canMakeOutgoing()) {
disconnect();
connection = device.connect(inParams, this);
if (connection == null && basicConnectionListener != null)
basicConnectionListener
.onConnectionFailedConnecting(new Exception(
"Couldn't create new connection"));
}
}
public void disconnect() {
IncomingPhoneActivity.incomingAlert = null;
if (connection != null) {
connection.disconnect(); // will null out in onDisconnected()
if (basicConnectionListener != null)
basicConnectionListener.onConnectionDisconnecting();
}
}
public void acceptConnection() {
if (pendingIncomingConnection != null) {
if (connection != null)
disconnect();
pendingIncomingConnection.accept();
connection = pendingIncomingConnection;
pendingIncomingConnection = null;
}
}
public void connecta(String phoneNumber) {
Toast.makeText(context, "Calling...", Toast.LENGTH_SHORT).show();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("group_id", "11");
// String capabilityToken;
try {
device = Twilio
.createDevice(decodedString, this /* DeviceListener */);
} catch (Exception e1) {
e1.printStackTrace();
}
try {
device.disconnectAll();
} catch (Exception e) {
e.printStackTrace();
}
connection = device.connect(parameters, this);
if (connection == null) {
Log.w(TAG, "Failed to create new connection");
}
}
public void ignoreIncomingConnection() {
if (pendingIncomingConnection != null) {
pendingIncomingConnection.ignore();
}
}
public boolean isConnected() {
return connection != null
&& connection.getState() == Connection.State.CONNECTED;
}
public Connection.State getConnectionState() {
return connection != null ? connection.getState()
: Connection.State.DISCONNECTED;
}
public boolean hasPendingConnection() {
return pendingIncomingConnection != null;
}
public boolean handleIncomingIntent(Intent intent) {
Device inDevice = intent.getParcelableExtra(Device.EXTRA_DEVICE);
Connection inConnection = intent
.getParcelableExtra(Device.EXTRA_CONNECTION);
if (inDevice == null && inConnection == null)
return false;
intent.removeExtra(Device.EXTRA_DEVICE);
intent.removeExtra(Device.EXTRA_CONNECTION);
if (pendingIncomingConnection != null) {
Log.i(TAG, "A pending connection already exists");
inConnection.ignore();
return false;
}
pendingIncomingConnection = inConnection;
pendingIncomingConnection.setConnectionListener(this);
return true;
}
public boolean canMakeOutgoing() {
if (device == null)
return false;
Map<Capability, Object> caps = device.getCapabilities();
return caps.containsKey(Capability.OUTGOING)
&& (Boolean) caps.get(Capability.OUTGOING);
}
public boolean canAcceptIncoming() {
if (device == null)
return false;
Map<Capability, Object> caps = device.getCapabilities();
return caps.containsKey(Capability.INCOMING)
&& (Boolean) caps.get(Capability.INCOMING);
}
public void setCallMuted(boolean isMuted) {
if (connection != null) {
connection.setMuted(isMuted);
}
}
#Override
/* DeviceListener */
public void onStartListening(Device inDevice) {
if (basicDeviceListener != null)
basicDeviceListener.onDeviceStartedListening();
}
#Override
/* DeviceListener */
public void onStopListening(Device inDevice) {
if (basicDeviceListener != null)
basicDeviceListener.onDeviceStoppedListening(null);
}
#Override
/* DeviceListener */
public void onStopListening(Device inDevice, int inErrorCode,
String inErrorMessage) {
if (basicDeviceListener != null)
basicDeviceListener.onDeviceStoppedListening(new Exception(
inErrorMessage));
}
#Override
/* DeviceListener */
public boolean receivePresenceEvents(Device inDevice) {
return false;
}
#Override
/* DeviceListener */
public void onPresenceChanged(Device inDevice, PresenceEvent inPresenceEvent) {
}
#Override
/* ConnectionListener */
public void onConnecting(Connection inConnection) {
if (basicConnectionListener != null)
basicConnectionListener.onConnectionConnecting();
}
#Override
/* ConnectionListener */
public void onConnected(Connection inConnection) {
updateAudioRoute();
if (basicConnectionListener != null)
basicConnectionListener.onConnectionConnected();
}
#Override
/* ConnectionListener */
public void onDisconnected(Connection inConnection) {
if (inConnection == connection) {
connection = null;
if (basicConnectionListener != null)
basicConnectionListener.onConnectionDisconnected();
} else if (inConnection == pendingIncomingConnection) {
pendingIncomingConnection = null;
if (basicConnectionListener != null)
basicConnectionListener.onIncomingConnectionDisconnected();
}
}
#Override
/* ConnectionListener */
public void onDisconnected(Connection inConnection, int inErrorCode,
String inErrorMessage) {
if (inConnection == connection) {
connection = null;
if (basicConnectionListener != null)
basicConnectionListener
.onConnectionFailedConnecting(new Exception(
inErrorMessage));
}
}
private class GetAuthTokenAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
IncomingPhone.this.reallyLogin(result);
}
#Override
protected String doInBackground(String... params) {
try {
capabilityToken = HttpHelper.httpGet(params[0]);
decodedString = capabilityToken.replace("\"", "");
} catch (Exception e) {
e.printStackTrace();
}
return decodedString;
}
}
}
And the activity which opens after getting incoming call via Service class.
public class IncomingPhoneActivity extends Activity implements LoginListener,
BasicConnectionListener, BasicDeviceListener, View.OnClickListener,
CompoundButton.OnCheckedChangeListener,
RadioGroup.OnCheckedChangeListener {
private static final Handler handler = new Handler();
public IncomingPhone phone;
SharedPreferences login_details;
Vibrator vibrator;
private LinearLayout disconnect_btn;
private LinearLayout mainButton;
private ToggleButton speakerButton;
private ToggleButton muteButton;
private EditText logTextBox;
static AlertDialog incomingAlert;
private EditText outgoingTextBox;
private EditText clientNameTextBox;
private Button capabilitesButton;
private CheckBox incomingCheckBox, outgoingCheckBox;
Button call_btn, dis_call_btn, updateButton;
public static String AUTH_PHP_SCRIPT, rating1, rating2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.call_screen);
Intent intent = getIntent();
Operator_id = intent.getStringExtra("operator_id");
gps = new GPSTracker(IncomingPhoneActivity.this);
if (gps.canGetLocation()) {
latitude = gps.getLatitude();
longitude = gps.getLongitude();
} else {
// gps.showSettingsAlert();
latitude = 0.00;
longitude = 0.00;
}
login_details = getSharedPreferences(LOGIN_DETAILS,
Context.MODE_PRIVATE);
if (login_details.contains("twilio_Id")) {
Twilio_id = login_details.getString("twilio_Id", "");
}
AUTH_PHP_SCRIPT = "http://xxxxxxxxxxxxxx/getGenToken?group_id="
+ Operator_id + "&twilio_id=" + Twilio_id + "&latitude="
+ latitude + "&longitude=" + longitude;
disconnect_btn = (LinearLayout) findViewById(R.id.d_call);
mainButton = (LinearLayout) findViewById(R.id.call);
call_btn = (Button) findViewById(R.id.call_btn);
dis_call_btn = (Button) findViewById(R.id.d_call_btn);
mainButton.setOnClickListener(this);
call_btn.setOnClickListener(this);
dis_call_btn.setOnClickListener(this);
disconnect_btn.setOnClickListener(this);
mainButton.setEnabled(false);
call_btn.setEnabled(false);
speakerButton = (ToggleButton) findViewById(R.id.speaker_btn);
speakerButton.setOnCheckedChangeListener(this);
muteButton = (ToggleButton) findViewById(R.id.mute_btn);
muteButton.setOnCheckedChangeListener(this);
logTextBox = (EditText) findViewById(R.id.log_text_box);
outgoingTextBox = (EditText) findViewById(R.id.outgoing_client);
clientNameTextBox = (EditText) findViewById(R.id.client_name);
clientNameTextBox.setText(DEFAULT_CLIENT_NAME);
capabilitesButton = (Button) findViewById(R.id.capabilites_button);
capabilitesButton.setOnClickListener(this);
outgoingCheckBox = (CheckBox) findViewById(R.id.outgoing);
incomingCheckBox = (CheckBox) findViewById(R.id.incoming);
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (MenuItems.Speaker == true) {
speakerButton.setVisibility(View.VISIBLE);
} else {
speakerButton.setVisibility(View.INVISIBLE);
}
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
phone = IncomingPhone.getInstance(getApplicationContext());
phone.setListeners(this, this, this);
phone.login(DEFAULT_CLIENT_NAME, outgoingCheckBox.isChecked(),
incomingCheckBox.isChecked());
}
private void syncMainButton() {
handler.post(new Runnable() {
public void run() {
if (IncomingPhone.decodedString.length() != 0) {
if (phone.isConnected()) {
switch (phone.getConnectionState()) {
default:
mainButton.setClickable(true);
mainButton.setEnabled(true);
call_btn.setEnabled(true);
mainButton.setVisibility(View.VISIBLE);
disconnect_btn.setVisibility(View.GONE);
disconnect_btn.setClickable(false);
break;
case DISCONNECTED:
mainButton.setVisibility(View.VISIBLE);
disconnect_btn.setVisibility(View.GONE);
disconnect_btn.setClickable(false);
break;
case CONNECTED:
mainButton.setVisibility(View.GONE);
disconnect_btn.setVisibility(View.VISIBLE);
disconnect_btn.setClickable(true);
break;
case CONNECTING:
mainButton.setVisibility(View.GONE);
disconnect_btn.setVisibility(View.VISIBLE);
disconnect_btn.setClickable(true);
break;
}
} else if (phone.hasPendingConnection()) {
mainButton.setClickable(true);
mainButton.setEnabled(true);
call_btn.setEnabled(true);
mainButton.setVisibility(View.VISIBLE);
disconnect_btn.setVisibility(View.GONE);
disconnect_btn.setClickable(false);
} else {
mainButton.setVisibility(View.VISIBLE);
disconnect_btn.setVisibility(View.GONE);
disconnect_btn.setClickable(false);
}
/*
* else { Toast.makeText(getApplicationContext(),
* "TRY AGAIN!", Toast.LENGTH_SHORT).show(); }
*/
}
}
});
}
public void onBackPressed() {
phone.disconnect();
incomingAlert = null;
Intent in = new Intent(IncomingPhoneActivity.this, MenuItems.class);
in.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(in);
finish();
}
class TokenTask extends AsyncTask<Void, Void, Void> {
String message;
JSONObject jsonResponse;
int crash_app;
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... params) {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpGet httppost = new HttpGet(AUTH_PHP_SCRIPT);
try {
HttpResponse response = httpclient.execute(httppost);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
if (entity != null) {
IncomingPhone.capabilityToken = EntityUtils
.toString(entity);
IncomingPhone.decodedString = IncomingPhone.capabilityToken
.replace("\"", "");
}
}
} catch (Exception e) {
crash_app = 5;
message = "Something went wrong. Please try again later.";
return null;
}
return null;
}
#Override
protected void onPostExecute(Void result) {
if (status.equals("success")) {
final Handler handler12 = new Handler();
handler12.postDelayed(new Runnable() {
public void run() {
mainButton.setEnabled(true);
call_btn.setEnabled(true);
mainButton
.setBackgroundResource(R.drawable.light_green_connect);
}
}, 3000);
}
if (status.equals("failure")) {
Toast.makeText(getApplicationContext(), message,
Toast.LENGTH_LONG).show();
// mainButton.setBackgroundColor(Color.parseColor("#4ca64c"));
mainButton.setBackgroundResource(R.drawable.dark_green_connect);
mainButton.setEnabled(false);
call_btn.setEnabled(false);
}
}
}
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
#Override
public void onResume() {
super.onResume();
if (phone.handleIncomingIntent(getIntent())) {
showIncomingAlert();
addStatusMessage(R.string.got_incoming);
if (Utils.isNetworkAvailable(IncomingPhoneActivity.this)) {
syncMainButton();
} else {
Toast.makeText(IncomingPhoneActivity.this,
"No internet connection!!", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (phone != null) {
phone.setListeners(null, null, null);
phone = null;
}
}
#Override
public void onClick(View view) {
if ((view.getId() == R.id.d_call) || (view.getId() == R.id.d_call_btn)) {
phone.disconnect();
incomingAlert = null;
phone.setSpeakerEnabled(false);
phone.setCallMuted(false);
Intent in = new Intent(IncomingPhoneActivity.this, MenuItems.class);
startActivity(in);
finish();
}
if ((view.getId() == R.id.call) || (view.getId() == R.id.call_btn)) {
} else if (view.getId() == R.id.capabilites_button) {
phone.login(clientNameTextBox.getText().toString(),
outgoingCheckBox.isChecked(), incomingCheckBox.isChecked());
}
}
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (group.getId() == R.id.input_select) {
if (checkedId == R.id.input_number) {
outgoingTextBox.setInputType(InputType.TYPE_CLASS_PHONE);
outgoingTextBox.setHint(R.string.outgoing_number);
} else {
outgoingTextBox.setInputType(InputType.TYPE_CLASS_TEXT);
outgoingTextBox.setHint(R.string.outgoing_client);
}
outgoingTextBox.setText("");
}
}
#Override
public void onCheckedChanged(CompoundButton button, boolean isChecked) {
if (button.getId() == R.id.speaker_btn) {
phone.setSpeakerEnabled(isChecked);
} else if (button.getId() == R.id.mute_btn) {
phone.setCallMuted(isChecked);
}
}
private void addStatusMessage(final String message) {
handler.post(new Runnable() {
#Override
public void run() {
logTextBox.append('-' + message + '\n');
}
});
}
private void addStatusMessage(int stringId) {
addStatusMessage(getString(stringId));
}
private void showIncomingAlert() {
handler.post(new Runnable() {
#Override
public void run() {
if (incomingAlert == null) {
notification = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
r = RingtoneManager.getRingtone(getApplicationContext(),
notification);
am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
switch (am.getRingerMode()) {
case AudioManager.RINGER_MODE_SILENT:
r.play();
break;
case AudioManager.RINGER_MODE_VIBRATE:
long pattern[] = { 0, 500, 200, 300, 500 };
vibrator.vibrate(pattern, 0);
break;
case AudioManager.RINGER_MODE_NORMAL:
r.play();
break;
}
incomingAlert = new AlertDialog.Builder(
IncomingPhoneActivity.this)
.setTitle(R.string.incoming_call)
.setCancelable(false)
.setMessage(R.string.incoming_call_message)
.setPositiveButton(R.string.answer,
new DialogInterface.OnClickListener() {
#Override
public void onClick(
DialogInterface dialog,
int which) {
switch (am.getRingerMode()) {
case AudioManager.RINGER_MODE_SILENT:
r.stop();
break;
case AudioManager.RINGER_MODE_VIBRATE:
vibrator.cancel();
break;
case AudioManager.RINGER_MODE_NORMAL:
r.stop();
break;
}
phone.acceptConnection();
disconnect_btn
.setVisibility(View.VISIBLE);
mainButton.setVisibility(View.GONE);
incomingAlert = null;
}
})
.setNegativeButton(R.string.ignore,
new DialogInterface.OnClickListener() {
#Override
public void onClick(
DialogInterface dialog,
int which) {
switch (am.getRingerMode()) {
case AudioManager.RINGER_MODE_SILENT:
r.stop();
break;
case AudioManager.RINGER_MODE_VIBRATE:
vibrator.cancel();
break;
case AudioManager.RINGER_MODE_NORMAL:
r.stop();
break;
}
phone.ignoreIncomingConnection();
incomingAlert = null;
}
})
.setOnCancelListener(
new DialogInterface.OnCancelListener() {
#Override
public void onCancel(
DialogInterface dialog) {
phone.ignoreIncomingConnection();
}
}).create();
incomingAlert.show();
}
}
});
}
private void hideIncomingAlert() {
handler.post(new Runnable() {
#Override
public void run() {
if (incomingAlert != null) {
incomingAlert.dismiss();
incomingAlert = null;
}
}
});
}
#Override
public void onLoginStarted() {
addStatusMessage(R.string.logging_in);
}
#Override
public void onLoginFinished() {
addStatusMessage(phone.canMakeOutgoing() ? R.string.outgoing_ok
: R.string.no_outgoing_capability);
addStatusMessage(phone.canAcceptIncoming() ? R.string.incoming_ok
: R.string.no_incoming_capability);
syncMainButton();
}
#Override
public void onLoginError(Exception error) {
if (error != null)
addStatusMessage(String.format(getString(R.string.login_error_fmt),
error.getLocalizedMessage()));
else
addStatusMessage(R.string.login_error_unknown);
syncMainButton();
}
#Override
public void onIncomingConnectionDisconnected() {
hideIncomingAlert();
addStatusMessage(R.string.incoming_disconnected);
syncMainButton();
}
#Override
public void onConnectionConnecting() {
addStatusMessage(R.string.attempting_to_connect);
syncMainButton();
}
#Override
public void onConnectionConnected() {
addStatusMessage(R.string.connected);
syncMainButton();
}
#Override
public void onConnectionFailedConnecting(Exception error) {
if (error != null)
addStatusMessage(String.format(
getString(R.string.couldnt_establish_outgoing_fmt),
error.getLocalizedMessage()));
else
addStatusMessage(R.string.couldnt_establish_outgoing);
}
#Override
public void onConnectionDisconnecting() {
addStatusMessage(R.string.disconnect_attempt);
syncMainButton();
}
#Override
public void onConnectionDisconnected() {
addStatusMessage(R.string.disconnected);
syncMainButton();
}
#Override
public void onConnectionFailed(Exception error) {
if (error != null)
addStatusMessage(String.format(
getString(R.string.connection_error_fmt),
error.getLocalizedMessage()));
else
addStatusMessage(R.string.connection_error);
syncMainButton();
}
#Override
public void onDeviceStartedListening() {
addStatusMessage(R.string.device_listening);
}
#Override
public void onDeviceStoppedListening(Exception error) {
if (error != null)
addStatusMessage(String.format(
getString(R.string.device_listening_error_fmt),
error.getLocalizedMessage()));
else
addStatusMessage(R.string.device_not_listening);
}
}
I'm trying to use the google download manager for downloading main and patch expansion files which are both uploaded with the apk. I'm pretty much following the google example. The download process starts but immediately stops with 'STATE_COMPLETED'. No error but the files are still missing. The App only works if I manually copy the files to the device.
This is my Download Activity:
public class DownloadActivity extends Activity implements IDownloaderClient {
private IStub mDownloaderClientStub;
private IDownloaderService mRemoteService;
private boolean downloadDoneRegistered = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_download);
startDownload();
}
#Override
protected void onResume() {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.connect(this);
}
super.onResume();
}
#Override
protected void onStop() {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.disconnect(this);
}
super.onStop();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.download, menu);
return true;
}
// IDownloaderClient
#Override
public void onServiceConnected(Messenger m) {
mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
}
#Override
public void onDownloadStateChanged(int newState) { //todo
switch (newState) {
case IDownloaderClient.STATE_IDLE:
case IDownloaderClient.STATE_CONNECTING:
case IDownloaderClient.STATE_FETCHING_URL:
case IDownloaderClient.STATE_DOWNLOADING:
break;
case IDownloaderClient.STATE_FAILED_CANCELED:
case IDownloaderClient.STATE_FAILED:
case IDownloaderClient.STATE_FAILED_FETCHING_URL:
case IDownloaderClient.STATE_FAILED_UNLICENSED:
downloadFailed();
break;
case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION:
case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION:
case IDownloaderClient.STATE_PAUSED_BY_REQUEST:
case IDownloaderClient.STATE_PAUSED_ROAMING:
case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE:
break;
case IDownloaderClient.STATE_COMPLETED:
downloadDone();
return;
default:
break;
}
}
#Override
public void onDownloadProgress(DownloadProgressInfo progress) {
float p = (float)progress.mOverallProgress;
if (progress.mOverallTotal>0) {
p /= (float)progress.mOverallTotal;
} else {
p = 0.0f;
}
String s = String.format(getString(R.string.download_progress).replace("#","%"),100.0f*p);
D.L(this,s);
setProgressBar(p);
setText(s);
}
//
private void startDownload() {
D.L(this,getString(R.string.download_checkfiles));
setProgressBar(0.0f);
setText(getString(R.string.download_checkfiles));
if (!expansionFilesDelivered()) {
D.L(this,"expansion files not downloaded so far");
setProgressBar(0.0f);
setText(String.format(getString(R.string.download_progress).replace("#","%"),0.0f));
try {
Intent launchIntent = DownloadActivity.this.getIntent();
Intent intentToLaunchThisActivityFromNotification = new Intent(DownloadActivity.this,DownloadActivity.this.getClass());
intentToLaunchThisActivityFromNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentToLaunchThisActivityFromNotification.setAction(launchIntent.getAction());
PendingIntent pendingIntent = PendingIntent.getActivity(DownloadActivity.this,0,intentToLaunchThisActivityFromNotification,PendingIntent.FLAG_UPDATE_CURRENT);
D.L(this,"start download service");
int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this,pendingIntent,DownloadService.class);
D.L(this,""+startResult+" <-compare-> "+DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED+"=NO_DOWNLOAD_REQUIRED");
if (startResult!=DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
D.L(this,"-> download required, create stub");
setText(String.format(getString(R.string.download_progress).replace("#","%"),0.0f));
mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,DownloadService.class);
return;
} else {
D.L(this,"no download required");
downloadDone();
}
} catch (NameNotFoundException e) {
D.L(this,e.getMessage());
downloadFailed();
}
} else {
// validate apk zip files(?)
D.L(this,"expansion files valid, no download required");
downloadDone();
}
}
boolean expansionFilesDelivered() {
if ((Download.MAIN_EXISTS) &&
(!Helpers.doesFileExist(this,Helpers.getExpansionAPKFileName(this,true,Download.MAIN_VERSION),Download.MAIN_SIZE,false))) {
return false;
}
if ((Download.PATCH_EXISTS) &&
(!Helpers.doesFileExist(this,Helpers.getExpansionAPKFileName(this,false,Download.PATCH_VERSION),Download.PATCH_SIZE,false))) {
return false;
}
return true;
}
private void setProgressBar(float value) {
((ProgressBar)findViewById(R.id.progressBar)).setProgress((int)(1000.0f*value));
}
private void setText(String text) {
((TextView)findViewById(R.id.textView)).setText(text);
}
private void downloadDone() {
if (!downloadDoneRegistered) {
downloadDoneRegistered = true;
D.L(this,"downloadDone(): download terminated");
setProgressBar(1.0f);
setText(getString(R.string.download_completed));
boolean fileAccess = true;
if (Download.MAIN_EXISTS) {
Download.SetMainFile(safeFileAccess(Helpers.getExpansionAPKFileName(this,true,Download.MAIN_VERSION)));
fileAccess = fileAccess && (Download.GetMainFile()!=null);
} else {
D.L(this,"no main expansion file");
}
if (Download.PATCH_EXISTS) {
Download.SetPatchFile(safeFileAccess(Helpers.getExpansionAPKFileName(this,false,Download.PATCH_VERSION)));
fileAccess = fileAccess && (Download.GetPatchFile()!=null);
} else {
D.L(this,"no patch expansion file");
}
if (fileAccess) {
D.L(this,"file access passed");
T.StartActivity(this,SplashActivity.class,true);
} else {
fileAccessFailed();
}
}
}
private File safeFileAccess(String fileName) {
D.L(this,"try to access file...");
File r = new File(
Environment.getExternalStorageDirectory()+File.separator+
"Android"+File.separator+
"obb"+File.separator+
getPackageName() ,
fileName);
D.L(this," "+r);
if (r.exists()) {
D.L(this," passed");
} else {
D.L(this," failed");
r = null;
}
return r;
}
private void downloadFailed() {
D.L(this,getString(R.string.download_failed));
setText(getString(R.string.download_failed));
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.download_failed_dialogtext));
builder.setPositiveButton(getString(R.string.download_dialog_okay),new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
finish();
}
});
builder.create().show();
}
private void fileAccessFailed() {
D.L(this,getString(R.string.download_accessfailed));
setText(getString(R.string.download_accessfailed));
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.download_accessfailed_dialogtext));
builder.setPositiveButton(getString(R.string.download_dialog_okay),new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
finish();
}
});
builder.create().show();
}
}
My Alarm Receiver:
public class DownloadAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
DownloaderClientMarshaller.startDownloadServiceIfRequired(context,intent,DownloadService.class);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
}
My Download Service:
public class DownloadService extends DownloaderService {
#Override
public String getPublicKey() {
return Download.BASE64_PUBLIC_KEY;
}
#Override
public byte[] getSALT() {
return Download.SALT;
}
#Override
public String getAlarmReceiverClassName() {
return DownloadAlarmReceiver.class.getName();
}
}
Some data stuff:
public class Download {
private static Download Instance = new Download();
public static Download GetInstance() { return Instance; }
//todo
public static final String BASE64_PUBLIC_KEY = "..actual key..";
public static final byte[] SALT = new byte[] {..numbers..};
public static final boolean MAIN_EXISTS = true;
public static final int MAIN_VERSION = 2;
public static final long MAIN_SIZE = 20971520L;
public static final boolean PATCH_EXISTS = true;
public static final int PATCH_VERSION = 2;
public static final long PATCH_SIZE = 10485760L;
…
Any ideas?