can't start intent startActivityForResult from class - java

I will be very happy if someone can help me, because I'm new at object programming. My problem is: I'm writting some app with bluetooth communication. I wrote all methods and successfully connect and transfer data between devices in MainActivity.class. I have also one SearchActivity.class which shows all devices in range on List, so user can pick one. Device is then passed through Intent to MainActivity, where connection starts. But because of nature of my app I must created separate class, just for Bluetooth communication called BluetoothService.class. I moved all methods for Bluetooth and other stuff to BluetoothService.class.
Now I even can't compile my project, because I get error at creating Intent for SearchActivity, I also get error startActivityForResult and onActivityResult methods.
First error is: The constructor Intent(BluetoothService, Class) is undefined
Second error: The method startActivityForResult(Intent, int) is undefined for the type BluetoothService
public void startConnection() {
// Create an intent for SearchActivity
Intent intent = new Intent(this, SearchActivity.class);
//start SearchActivity through intent and expect for result.
//The result is based on result code, which is REQUEST_DISCOVERY
startActivityForResult(intent, REQUEST_DISCOVERY);
}
When I was calling method startConnection() from MainActivity everything worked, but now I it doesn't. I think the problem is, that I can't create new Activity from non-activity class.
Next error is in onActivityResult method: *RESULT_OK cannot be resolved to a variable*
//on ActivityResult method is called, when other activity returns result through intent!
//when user selected device in SearchActivity, result is passed through intent with //requestCode, resultCode (intent data + requestCode + resultCode)
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != REQUEST_DISCOVERY) {
Log.d("Debug", ">>intent REQUEST_DISCOVERY failed!");
return;
}
if (resultCode != RESULT_OK) {
Log.d("Debug", ">>intent RESULT_OK failed!");
return;
}
Log.d("Debug", ">>onActivityResult!");
final BluetoothDevice device = data.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.d(device.getName(), "Name of Selected Bluetoothdevice");
new Thread () {
public void run() {
//call connect function with device argument
connect(device);
};
}.start();
}
Please, tell me how can I solve this. If you need more info or code tell me. Thanks.
public class SearchActivity extends ListActivity
{
//name of LxDevices, that will be shown on search
private String nameOfLxDevice = "DEBUG";
private Handler handler = new Handler();
/* Get Default Adapter */
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
/* Storage the BT devices */
private List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
/* Discovery is Finished */
private volatile boolean discoveryFinished;
/* Start search device */
private Runnable discoveryWorker = new Runnable() {
public void run()
{
//To start discovering devices, simply call startDiscovery(). The process is asynchronous and the method will
//immediately return with a boolean indicating whether discovery has successfully started.
mBluetoothAdapter.startDiscovery();
Log.d("debug", ">>Starting Discovery");
for (;;)
{
if (discoveryFinished)
{
Log.d("debug", ">>Finished");
break;
}
try
{
Thread.sleep(100);
}
catch (InterruptedException e){}
}
}
};
/* when discovery is finished, this will be called */
//Your application must register a BroadcastReceiver for the ACTION_FOUND Intent in order to receive information about each device discovered.
//For each device, the system will broadcast the ACTION_FOUND Intent. This Intent carries the extra fields EXTRA_DEVICE and EXTRA_CLASS,
//containing a BluetoothDevice and a BluetoothClass, respectively
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
/* get the search results */
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//add it on List<BluetoothDevice>
devices.add(device);
//show found LxDevice on list
showDevices();
}
}
};
private BroadcastReceiver discoveryReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
/* unRegister Receiver */
Log.d("debug", ">>unregisterReceiver");
unregisterReceiver(mBroadcastReceiver);
unregisterReceiver(this);
discoveryFinished = true;
}
};
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
/* BT isEnable */
if (!mBluetoothAdapter.isEnabled())
{
Log.w("debug", ">>BT is disable!");
finish();
return;
}
/* Register Receiver*/
IntentFilter discoveryFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(discoveryReceiver, discoveryFilter);
IntentFilter foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mBroadcastReceiver, foundFilter);
/* show a dialog "Scanning..." */
SamplesUtils.indeterminate(SearchActivity.this, handler, "Scanning for LX devices..", discoveryWorker, new OnDismissListener() {
public void onDismiss(DialogInterface dialog)
{
for (; mBluetoothAdapter.isDiscovering();) {
// Discovery is resource intensive. Make sure it isn't going on when you attempt to connect and pass your message.
mBluetoothAdapter.cancelDiscovery();
}
discoveryFinished = true;
}
}, true);
}
/* Show devices list */
private void showDevices()
{
//Create a list of strings
List<String> list = new ArrayList<String>();
for (int i = 0, size = devices.size(); i < size; ++i) {
StringBuilder b = new StringBuilder();
BluetoothDevice d = devices.get(i);
b.append(d.getName());
b.append('\n');
b.append(d.getAddress());
String s = b.toString();
list.add(s);
}
Log.d("debug", ">>showDevices");
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
handler.post(new Runnable() {
public void run()
{
setListAdapter(adapter);
}
});
}
/* Select device */
protected void onListItemClick(ListView l, View v, int position, long id) {
Log.d("debug", ">>Click device");
Intent result = new Intent();
result.putExtra(BluetoothDevice.EXTRA_DEVICE, devices.get(position));
setResult(RESULT_OK, result);
finish();
}
}
In MainActivity I am doing:
// Initialize the BluetoothChatService to perform bluetooth connections
mBluetoothService = new BluetoothService(this);
Constructor in BluetoothService is:
public BluetoothService(Context context) {
}
connect method:
protected void connect(BluetoothDevice device) {
try {
//Create a Socket connection: need the server's UUID number of registered
BluetoothSocket socket = null;
socket = device.createRfcommSocketToServiceRecord(MY_UUID);
socket.connect();
//Create temporary input and output stream
InputStreamtmpIn=socket.getInputStream();
OutputStream tmpOut = socket.getOutputStream();
//for use purposes
mmSocket = socket;
mmOutStream = tmpOut;
mmInStream = tmpIn;
tmpOut.write("Device connected..".getBytes());
//start Thread for receiving data over bluetooth
//dataReceiveThread.start();
} catch (IOException e) {
Log.e("Colibri2BB BT", "", e);
}
}

Your BluettoothService class is not a context and to initialise an Intent you need a context.So try creating your class like this:
public class BluettoothService{
Activity activity;
BluettoothService(Activity activity){
this.activity=activity;
}
public void startConnection() {
// Create an intent for SearchActivity
Intent intent = new Intent(activity, SearchActivity.class);
//start SearchActivity through intent and expect for result.
//The result is based on result code, which is REQUEST_DISCOVERY
activity.startActivityForResult(intent, REQUEST_DISCOVERY);
}
}
And you can create the BluettoothService class this way from any activity:
BluettoothService bluetooth=new BluettoothService(this);
Edit:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != REQUEST_DISCOVERY) {
Log.d("Debug", ">>intent REQUEST_DISCOVERY failed!");
return;
}
if (resultCode != Activity.RESULT_OK) {
Log.d("Debug", ">>intent RESULT_OK failed!");
return;
}
Log.d("Debug", ">>onActivityResult!");
final BluetoothDevice device = data.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.d(device.getName(), "Name of Selected Bluetoothdevice");
new Thread () {
public void run() {
//call connect function with device argument
connect(device);
};
}.start();
}

You can't use this of a Service to start an ActivityForResult

You should to specify the #override for the onActivityResult().
Your code should to be put into a class who extends 'activity' (android.app.Activity).
It's for that you have also this :
Next error is in onActivityResult method: *RESULT_OK cannot be resolved to a variable*
This cannot be resolved because your class don't extends 'Activity'

//create this class that hold application context.
public class Application_Manager extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
Application_Manager.context = getApplicationContext();
}
public static Context getAppContext() {
return Application_Manager.context;
}
}
//use this class getAppcontext() to get context in non-activity class.
public class BluettoothService{
static Context context=Application_Manager.getAppContext();
public void startConnection() {
Intent intent = new Intent(context, SearchActivity.class);
context.startActivityForResult(intent, REQUEST_DISCOVERY);//change edited
}
}

Related

Why does the UI stop updating countdown after restarting the app while using intent service?

I am trying to show a countdown in a textview from a loop inside an Intent Service. I am using the result receiver class for the communication between Intent Service and Activity. It works fine when I start the service for the first time. The textview shows the countdown for each time the loop runs in the service.
But when I close and launch the app again the textview doesn't show the countdown and only shows the hard coded text, while on the other hand the service stills runs in the background.
Here is my code snippet for the MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final String RECEIVER_INTENT_EXTRA_NAME = "message_receiver_intent_extra";
private static final String TAG = "MainActivity";
private Intent intent;
MyIntentService myIntentService;
public TextView serviceCountdown;
private Button startButton, stopButton;
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
myIntentService = new MyIntentService();
startButton = findViewById(R.id.startServiceButton);
stopButton = findViewById(R.id.stopServiceButton);
startButton.setOnClickListener(this);
stopButton.setOnClickListener(this);
handler = new Handler();
serviceCountdown = findViewById(R.id.serviceCountdown);
MessageReceiver messageReceiver = new MessageReceiver(handler);
// send intent service
intent = new Intent(this, MyIntentService.class);
intent.putExtra(RECEIVER_INTENT_EXTRA_NAME, messageReceiver);
}
#Override
public void onClick(View v) {
if (startButton.equals(v)) {
ContextCompat.startForegroundService(getApplicationContext(), intent);
}
if (stopButton.equals(v)){
stopService(intent);
}
}
public class MessageReceiver extends ResultReceiver {
public MessageReceiver(Handler handler) {
super(handler);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == 1 && resultData != null){
final String countdown = resultData.getString("countdown");
handler.post(new Runnable() {
#Override
public void run() {
serviceCountdown.setText(countdown);
}
});
}
}
}
}
And here is my code for the Intent Service Class
public class MyIntentService extends IntentService {
private static final String CHANNEL_ID = "my_channel_id";
private static final String TAG = "MyIntentService";
public MyIntentService() {
super("MyIntentService");
setIntentRedelivery(true);
}
#Override
public void onCreate() {
super.onCreate();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent,0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("My Service Title")
.setContentText("This is sample notification text")
.setSmallIcon(R.drawable.ic_battery)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
ResultReceiver resultReceiver = intent.getParcelableExtra(MainActivity.RECEIVER_INTENT_EXTRA_NAME);
Log.d(TAG, "onHandleIntent: called");
synchronized (this) {
for (int i = 10; i >= 0; i--) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "Service is looping : " + i);
Bundle bundle = new Bundle();
bundle.putString("countdown", String.valueOf(i));
resultReceiver.send(1, bundle);
}
}
}
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy: called");
super.onDestroy();
}
}
In the real project, my intention is not to using the loop to show a countdown. It is just for testing and debugging purpose.
Use Local Broadcast Receiver from your service to activity. Now you getting the ResultReceiver from the MainActivity Intent. When the activity destroyed intents are also destroyed.
Use this Broadcast Receiver code in your service class.
LocalBroadcastManager localBroadcastManager =
LocalBroadcastManager.getInstance(this);
Intent sendIntent = new Intent(INTENT_ACTION_KEY);
sendIntent.putExtra(DATA_KEY, data);
localBroadcastManager.sendBroadcast(sendIntent);
Get this local broadcast receiver in your activity.
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
//Perform your logic.
}
}
};
Make sure you register this broadcast when activity starts and unregister it when stop.
#Override
public void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver((broadcastReceiver),
new IntentFilter(INTENT_ACTION_KEY));
}
#Override
public void onStop() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
super.onStop();
}

How to stop a VpnService that was called with prepare() and startService()?

I't trying to implement a local VpnService to have my app do some tasks, but I'm a little confused as to how to stop it one it started. The VpnService class and client activity are based on this repo:
https://github.com/hexene/LocalVPN
The caller activity is basically this:
public class MainActivity extends AppCompatActivity {
private static final int VPN_REQUEST_CODE = 0x0F;
private boolean waitingForVPNStart;
private BroadcastReceiver vpnStateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (LocalVPNService.BROADCAST_VPN_STATE.equals(intent.getAction()))
if (intent.getBooleanExtra("running", false))
waitingForVPNStart = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button vpnButton = (Button)findViewById(R.id.vpn);
vpnButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startVPN();
}
});
final Button vpnStopButton = (Button)findViewById(R.id.stopVpnButton);
vpnStopButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopVPN();
}
});
waitingForVPNStart = false;
LocalBroadcastManager.getInstance(this).registerReceiver(vpnStateReceiver,
new IntentFilter(LocalVPNService.BROADCAST_VPN_STATE));
}
private void startVPN() {
Intent vpnIntent = VpnService.prepare(this);
if (vpnIntent != null)
startActivityForResult(vpnIntent, VPN_REQUEST_CODE); //Prepare to establish a VPN connection. This method returns null if the VPN application is already prepared or if the user has previously consented to the VPN application. Otherwise, it returns an Intent to a system activity.
else
onActivityResult(VPN_REQUEST_CODE, RESULT_OK, null);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == VPN_REQUEST_CODE && resultCode == RESULT_OK) {
waitingForVPNStart = true;
startService(new Intent(this, LocalVPNService.class));
enableButton(false);
}
}
What confuses me is: how would I call the service's onDestroy() method or something similar if I don't keep an instance if it in my main activity?
I looked at this answer and this and seen implementations of stopService, but I'm not sure how to handle the Intent, because it's not only used to call startService() but also involved in calling VpnService.prepare().
Edit: I tried
stopService(new Intent(this, LocalVPNService.class)); but it doesn't stop it. I tried stopService(vpnIntent); and IT WORKS, but makes my app crash/close.
In your LocalVPNService class create a new broadcast:
private BroadcastReceiver stopBr = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if ("stop_kill".equals(intent.getAction())) {
stopself();
}
}
};
and in the onCreate method add this:
LocalBroadcastManager lbm =
LocalBroadcastManager.getInstance(this);
lbm.registerReceiver(stopBr, new IntentFilter("stop_kill"));
in your activity:
Intent intent = new Intent("stop_kill");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

USB Host Android Cannot Send String

I wanted my Android to communicate with an Arduino using an USB host. I've tried many references but can't seem to send any char to my Arduino. I can detect my Arduino but sending char or string to it is frustrating. Here are my codes:
MainActivity.java
public class MainActivity extends AppCompatActivity {
UsbDevice device=null;
UsbManager manager=null;
PendingIntent mPermissionIntent;
UsbInterface intf;
UsbEndpoint endpoint;
UsbDeviceConnection connection;
Button find;
Button send;
TextView hello;
UsbManager mUsbManager;
private static final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION";
private byte[] bytes;
private static int TIMEOUT = 0;
private boolean forceClaim = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
find = (Button) findViewById(R.id.Find);
send = (Button) findViewById(R.id.Send);
hello = (TextView) findViewById(R.id.hello);
find.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
hello.setText("");
checkInfo();
}
});
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(device!=null) {
intf = device.getInterface(0);
endpoint = intf.getEndpoint(0);
connection = mUsbManager.openDevice(device);
hello.setText("Kirim");
String kirim = "a";
bytes = kirim.getBytes();
connection.claimInterface(intf, forceClaim);
connection.bulkTransfer(endpoint, bytes, bytes.length, 0);
}
else{
Toast.makeText(MainActivity.this,"Device ==
null",Toast.LENGTH_SHORT);
}
}
});
private void checkInfo(){
manager=(UsbManager) getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(this,0,new
Intent(ACTION_USB_PERMISSION),0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver,filter);
HashMap<String,UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
String i="";
int j=0;
while(deviceIterator.hasNext()){
device = deviceIterator.next();
manager.requestPermission(device,mPermissionIntent);
i += "\n" + "DeviceID: " + device.getDeviceId() + "\n"
+ "DeviceName: " + device.getDeviceName() + "\n"
+ "DeviceClass: " + device.getDeviceClass() + " - "
+ "DeviceSubClass: " + device.getDeviceSubclass() + "\n"
+ "VendorID: " + device.getVendorId() + "\n"
+ "ProductID: " + device.getProductId() + "\n";
j++;
}
hello.setText(i);
}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice) intent
.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
// call method to set up device communication
}
} else {
Log.d("ERROR", "permission denied for device " +
device);
}
}
}
}
};
}
I iterate using a find button and send using a send button. The iteration went just fine, but the sending didn't work. I needed to send just a character to the Arduino. My phone supports OTG and had been tested using other serial communication application to send char to Arduino and it works just fine.
Thanks in advance
using the usb serial lib in releases section at: https://github.com/felHR85/UsbSerial then import the lib and install dependencies as shown in the url. For solving the problem you can create a service class that handles usb related stuff (look at usb host android documentation for details: https://developer.android.com/guide/topics/connectivity/usb/host.html
as follows:
public class UsbService extends Service {
public static final String TAG = "UsbService";
public static final String ACTION_USB_READY = "com.felhr.connectivityservices.USB_READY";
public static final String ACTION_USB_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED";
public static final String ACTION_USB_DETACHED = "android.hardware.usb.action.USB_DEVICE_DETACHED";
public static final String ACTION_USB_NOT_SUPPORTED = "com.felhr.usbservice.USB_NOT_SUPPORTED";
public static final String ACTION_NO_USB = "com.felhr.usbservice.NO_USB";
public static final String ACTION_USB_PERMISSION_GRANTED = "com.felhr.usbservice.USB_PERMISSION_GRANTED";
public static final String ACTION_USB_PERMISSION_NOT_GRANTED = "com.felhr.usbservice.USB_PERMISSION_NOT_GRANTED";
public static final String ACTION_USB_DISCONNECTED = "com.felhr.usbservice.USB_DISCONNECTED";
public static final String ACTION_CDC_DRIVER_NOT_WORKING = "com.felhr.connectivityservices.ACTION_CDC_DRIVER_NOT_WORKING";
public static final String ACTION_USB_DEVICE_NOT_WORKING = "com.felhr.connectivityservices.ACTION_USB_DEVICE_NOT_WORKING";
public static final int MESSAGE_FROM_SERIAL_PORT = 0;
public static final int CTS_CHANGE = 1;
public static final int DSR_CHANGE = 2;
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
private static final int BAUD_RATE = 9600; // BaudRate. Change this value if you need
public static boolean SERVICE_CONNECTED = false;
private IBinder binder = new UsbBinder();
private UsbService context;
private Handler mHandler;
private UsbManager usbManager;
private UsbDevice device;
private UsbDeviceConnection connection;
private UsbSerialDevice serialPort;
private boolean serialPortConnected;
/*
* Data received from serial port will be received here. Just populate onReceivedData with your code
* In this particular example. byte stream is converted to String and send to UI thread to
* be treated there.
*/
private UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() {
#Override
public void onReceivedData(byte[] arg0) {
try {
String data = new String(arg0, "UTF-8");
if (mHandler != null)
mHandler.obtainMessage(MESSAGE_FROM_SERIAL_PORT, data).sendToTarget();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
};
/*
* State changes in the CTS line will be received here
*/
private UsbSerialInterface.UsbCTSCallback ctsCallback = new UsbSerialInterface.UsbCTSCallback() {
#Override
public void onCTSChanged(boolean state) {
if(mHandler != null)
mHandler.obtainMessage(CTS_CHANGE).sendToTarget();
}
};
/*
* State changes in the DSR line will be received here
*/
private UsbSerialInterface.UsbDSRCallback dsrCallback = new UsbSerialInterface.UsbDSRCallback() {
#Override
public void onDSRChanged(boolean state) {
if(mHandler != null)
mHandler.obtainMessage(DSR_CHANGE).sendToTarget();
}
};
/*
* Different notifications from OS will be received here (USB attached, detached, permission responses...)
* About BroadcastReceiver: http://developer.android.com/reference/android/content/BroadcastReceiver.html
*/
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context arg0, Intent arg1) {
if (arg1.getAction().equals(ACTION_USB_PERMISSION)) {
boolean granted = arg1.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
if (granted) // User accepted our USB connection. Try to open the device as a serial port
{
Intent intent = new Intent(ACTION_USB_PERMISSION_GRANTED);
arg0.sendBroadcast(intent);
connection = usbManager.openDevice(device);
new ConnectionThread().start();
} else // User not accepted our USB connection. Send an Intent to the Main Activity
{
Intent intent = new Intent(ACTION_USB_PERMISSION_NOT_GRANTED);
arg0.sendBroadcast(intent);
}
} else if (arg1.getAction().equals(ACTION_USB_ATTACHED)) {
if (!serialPortConnected)
findSerialPortDevice(); // A USB device has been attached. Try to open it as a Serial port
} else if (arg1.getAction().equals(ACTION_USB_DETACHED)) {
// Usb device was disconnected. send an intent to the Main Activity
Intent intent = new Intent(ACTION_USB_DISCONNECTED);
arg0.sendBroadcast(intent);
if (serialPortConnected) {
serialPort.close();
}
serialPortConnected = false;
}
}
};
/*
* onCreate will be executed when service is started. It configures an IntentFilter to listen for
* incoming Intents (USB ATTACHED, USB DETACHED...) and it tries to open a serial port.
*/
#Override
public void onCreate() {
this.context=this;
serialPortConnected = false;
UsbService.SERVICE_CONNECTED = true;
setFilter();
usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
findSerialPortDevice();
}
/* MUST READ about services
* http://developer.android.com/guide/components/services.html
* http://developer.android.com/guide/components/bound-services.html
*/
#Override
public IBinder onBind(Intent intent) {
return binder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
serialPort.close();
unregisterReceiver(usbReceiver);
UsbService.SERVICE_CONNECTED = false;
}
/*
* This function will be called from MainActivity to write data through Serial Port
*/
public void write(byte[] data) {
if (serialPort != null)
serialPort.write(data);
}
public void setHandler(Handler mHandler) {
this.mHandler = mHandler;
}
private void findSerialPortDevice() {
// This snippet will try to open the first encountered usb device connected, excluding usb root hubs
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
if (!usbDevices.isEmpty()) {
// first, dump the hashmap for diagnostic purposes
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
Log.d(TAG, String.format("USBDevice.HashMap (vid:pid) (%X:%X)-%b class:%X:%X name:%s",
device.getVendorId(), device.getProductId(),
UsbSerialDevice.isSupported(device),
device.getDeviceClass(), device.getDeviceSubclass(),
device.getDeviceName()));
}
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
int deviceVID = device.getVendorId();
int devicePID = device.getProductId();
// if (deviceVID != 0x1d6b && (devicePID != 0x0001 && devicePID != 0x0002 && devicePID != 0x0003) && deviceVID != 0x5c6 && devicePID != 0x904c) {
if (UsbSerialDevice.isSupported(device)) {
// There is a supported device connected - request permission to access it.
requestUserPermission();
break;
} else {
connection = null;
device = null;
}
}
if (device==null) {
// There are no USB devices connected (but usb host were listed). Send an intent to MainActivity.
Intent intent = new Intent(ACTION_NO_USB);
sendBroadcast(intent);
}
} else {
Log.d(TAG, "findSerialPortDevice() usbManager returned empty device list." );
// There is no USB devices connected. Send an intent to MainActivity
Intent intent = new Intent(ACTION_NO_USB);
sendBroadcast(intent);
}
}
private void setFilter() {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USB_PERMISSION);
filter.addAction(ACTION_USB_DETACHED);
filter.addAction(ACTION_USB_ATTACHED);
registerReceiver(usbReceiver, filter);
}
/*
* Request user permission. The response will be received in the BroadcastReceiver
*/
private void requestUserPermission() {
Log.d(TAG, String.format("requestUserPermission(%X:%X)", device.getVendorId(), device.getProductId() ) );
PendingIntent mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device, mPendingIntent);
}
public class UsbBinder extends Binder {
public UsbService getService() {
return UsbService.this;
}
}
/*
* A simple thread to open a serial port.
* Although it should be a fast operation. moving usb operations away from UI thread is a good thing.
*/
private class ConnectionThread extends Thread {
#Override
public void run() {
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
if (serialPort != null) {
if (serialPort.open()) {
serialPortConnected = true;
serialPort.setBaudRate(BAUD_RATE);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
/**
* Current flow control Options:
* UsbSerialInterface.FLOW_CONTROL_OFF
* UsbSerialInterface.FLOW_CONTROL_RTS_CTS only for CP2102 and FT232
* UsbSerialInterface.FLOW_CONTROL_DSR_DTR only for CP2102 and FT232
*/
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
serialPort.read(mCallback);
serialPort.getCTS(ctsCallback);
serialPort.getDSR(dsrCallback);
//
// Some Arduinos would need some sleep because firmware wait some time to know whether a new sketch is going
// to be uploaded or not
//Thread.sleep(2000); // sleep some. YMMV with different chips.
// Everything went as expected. Send an intent to MainActivity
Intent intent = new Intent(ACTION_USB_READY);
context.sendBroadcast(intent);
} else {
// Serial port could not be opened, maybe an I/O error or if CDC driver was chosen, it does not really fit
// Send an Intent to Main Activity
if (serialPort instanceof CDCSerialDevice) {
Intent intent = new Intent(ACTION_CDC_DRIVER_NOT_WORKING);
context.sendBroadcast(intent);
} else {
Intent intent = new Intent(ACTION_USB_DEVICE_NOT_WORKING);
context.sendBroadcast(intent);
}
}
} else {
// No driver for given device, even generic CDC driver could not be loaded
Intent intent = new Intent(ACTION_USB_NOT_SUPPORTED);
context.sendBroadcast(intent);
}
}
}
}
then in your main activity put this snippets:
java
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case UsbService.ACTION_USB_PERMISSION_GRANTED: // USB PERMISSION GRANTED
Toast.makeText(context, "USB Ready", Toast.LENGTH_SHORT).show();
break;
case UsbService.ACTION_USB_PERMISSION_NOT_GRANTED: // USB PERMISSION NOT GRANTED
Toast.makeText(context, "USB Permission not granted", Toast.LENGTH_SHORT).show();
break;
case UsbService.ACTION_NO_USB: // NO USB CONNECTED
Toast.makeText(context, "No USB connected", Toast.LENGTH_SHORT).show();
break;
case UsbService.ACTION_USB_DISCONNECTED: // USB DISCONNECTED
Toast.makeText(context, "USB disconnected", Toast.LENGTH_SHORT).show();
break;
case UsbService.ACTION_USB_NOT_SUPPORTED: // USB NOT SUPPORTED
Toast.makeText(context, "USB device not supported", Toast.LENGTH_SHORT).show();
break;
}
}
};
private UsbService usbService;
public TextView display;
private EditText editText;
private MyHandler mHandler;
private final ServiceConnection usbConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
usbService = ((UsbService.UsbBinder) arg1).getService();
usbService.setHandler(mHandler);
// Toast.makeText(getApplicationContext(),"dentro on service connected " + usbService, Toast.LENGTH_SHORT).show();
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
usbService = null;
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.operacion);
mHandler = new MyHandler(this);
// your stuff here
#Override
public void onResume() {
super.onResume();
// Toast.makeText(getApplicationContext(),"on resume ", Toast.LENGTH_SHORT).show();
setFilters(); // Start listening notifications from UsbService
startService(UsbService.class, usbConnection, null); // Start UsbService(if it was not started before) and Bind it
// Toast.makeText(getApplicationContext(),"despues de start y weas ", Toast.LENGTH_SHORT).show();
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(mUsbReceiver);
unbindService(usbConnection);
}
private void startService(Class<?> service, ServiceConnection serviceConnection, Bundle extras) {
// Toast.makeText(getApplicationContext(),"start1", Toast.LENGTH_SHORT).show();
if (!UsbService.SERVICE_CONNECTED) {
Intent startService = new Intent(this, service);
if (extras != null && !extras.isEmpty()) {
Set<String> keys = extras.keySet();
for (String key : keys) {
String extra = extras.getString(key);
startService.putExtra(key, extra);
}
}
startService(startService);
// Toast.makeText(getApplicationContext(),"dp metodo start", Toast.LENGTH_SHORT).show();
}
Intent bindingIntent = new Intent(this, service);
bindService(bindingIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
private void setFilters() {
IntentFilter filter = new IntentFilter();
filter.addAction(UsbService.ACTION_USB_PERMISSION_GRANTED);
filter.addAction(UsbService.ACTION_NO_USB);
filter.addAction(UsbService.ACTION_USB_DISCONNECTED);
filter.addAction(UsbService.ACTION_USB_NOT_SUPPORTED);
filter.addAction(UsbService.ACTION_USB_PERMISSION_NOT_GRANTED);
registerReceiver(mUsbReceiver, filter);
}
public void getCurrentTimeUsingDate(){
String currentDateTimeString2 = DateFormat.getDateInstance().format(new Date());
TextView txtView3 = (TextView) findViewById(R.id.textView4);
txtView3.setText(""+currentDateTimeString2);
}
private static class MyHandler extends Handler {
private final WeakReference<Pag4> mActivity;
public MyHandler(Pag4 activity) {
mActivity = new WeakReference<>(activity);
}
Integer conta = 0;
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UsbService.MESSAGE_FROM_SERIAL_PORT:
String data = (String) msg.obj;
conta++;
break;
case UsbService.CTS_CHANGE:
Toast.makeText(mActivity.get(), "CTS_CHANGE",Toast.LENGTH_LONG).show();
break;
case UsbService.DSR_CHANGE:
Toast.makeText(mActivity.get(), "DSR_CHANGE",Toast.LENGTH_LONG).show();
break;
}
}
}
}
you make a button (btn3 in the example) and then add the listener as follows:
java
bt3.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
String auxi2="1"; // put whatever you need to send here
if (!auxi2.equals("")) {
String data = auxi2;
if (usbService != null) { // if UsbService was correctly binded, Send data
usbService.write(data.getBytes());
// Toast.makeText(getApplicationContext(),"auxi2 escrito"+ auxi2, Toast.LENGTH_SHORT).show();
}
}
}
});
Hope is clear, I assume you know how to import libs, and make a button, put the permission in manifiest, dependencies. Details about this in android doc link already posted upper in my answer.

Single function to retrive data from Broadcast receiver

I have a function ReadConfig in non activity class which is invoked by a Service. This function uses IntentService to read data from a file.
Function in non activity class
//Start of globalVariables
public static boolean received;
public static String actionID = "ACTION_ID";
public static ArrayList<String> configData;
public static BroadcastReceiver configDataReceiver;
//End of globalVariables
public static List<String> ReadConfig(Context context, String configFileName)
{
configDataReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context arg0, Intent intent)
{
if(intent.getAction().equals(actionID))
{
configData = intent.getStringArrayListExtra("CONFIGDATA");
received = true;
}
}
};
LocalBroadcastManager.getInstance(context)
.registerReceiver(configDataReceiver,new IntentFilter(actionID));
Intent workRequest = new Intent(context,IOConfigurations.class);
workRequest.putExtra("OPERATION","READ");
workRequest.putExtra("FILENAME",configFileName);
//Calling intentservice
context.startService(workRequest);
//Wait for broadcast receiver to get data and assign to global variables
while (!received)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
LocalBroadcastManager.getInstance(context).unregisterReceiver(configDataReceiver);
return configData;
}
Intent Service
Intent configData = new Intent(actionID);
configData.putStringArrayListExtra("CONFIGDATA",FileOperations.readFile(fileName));
LocalBroadcastManager.getInstance(this).sendBroadcast(configData);
The intent service is getting invoked and broadcasts the data but the receiver however doesn't receive any data from Broadcast manager and the while loop continues for ever.
check my comments
public static List<String> ReadConfig(Context context, String configFileName)
{
configDataReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context arg0, Intent intent)
{
if(intent.getAction().equals(actionID))
{
configData = intent.getStringArrayListExtra("CONFIGDATA");
received = true;
}
}
};
LocalBroadcastManager.getInstance(context)
.registerReceiver(configDataReceiver,new IntentFilter(actionID));
Intent workRequest = new Intent(context,IOConfigurations.class);
workRequest.putExtra("OPERATION","READ");
workRequest.putExtra("FILENAME",configFileName);
//Calling intentservice
context.startService(workRequest);
//Wait for broadcast receiver to get data and assign to global variables
while (!received)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
// Why here your unregistering the broacast listener,
// Your registering and unregistering in same call, unregiter when your work is done
LocalBroadcastManager.getInstance(context).unregisterReceiver(configDataReceiver);
return configData;
}

Unable to receive broadcast from Service

The issue I am having is in regards to receiving a broadcast from a service that is within an android library project.
Why am I unable to receive the broadcast? does it have to do with all the service/interface logic being in a seperate android library project?
Here is the broadcast from the service
broadcastReceivedMessage("THE TOPIC", "THE MESSAGE");
Here is the method within the service
private void broadcastReceivedMessage(final String topic, final String message) {
/* handler.post(new Runnable() {
#Override
public void run() {*/
Intent broadcastIntent = new Intent(CALLBACK_ACTION);
broadcastIntent.setAction(ON_MESSAGE_RECEIVED);
broadcastIntent.putExtra(TOPIC_STR, topic);
broadcastIntent.putExtra(MESSAGE_STR, message);
sendBroadcast(broadcastIntent);
/* }
});*/
}
Inside a class that implements many interfaces, this is where I am registering to listen for a specific intent filter.
#Override
public void connect(String address, int port) {
IntentFilter filter = new IntentFilter(MQTTService2.CALLBACK_ACTION);
LocalBroadcastManager.getInstance(getContext()).registerReceiver(serviceActionReceiver, filter);
Bundle args = new Bundle();
args.putString(MQTTService2.BROKER_ADDR_STR, address);
args.putInt(MQTTService2.BROKER_PORT_INT, port);
startService(MQTTService2.ACTION_CONNECT, args);
}
Inside an Activity where I expect to receive a callback from the interfaces and get my broadcast
MQTTEventHandler mHandler = new MQTTEventHandler() {
#Override
public void onStatusChanged(CommunicatorStatus status, String message) {
// TODO Auto-generated method stub
Log.e("onStatusChanged", "----------------Status Changed------------");
Log.e("STATUS: ", status.toString());
Log.e("MESSAGE: ", message);
Log.e("onStatusChanged", "--------------------------------------------");
}
#Override
public void onMessageReceived(String topic, String message) {
// TODO Auto-generated method stub
Log.e("onMessageReceived", "----------------Message Received------------");
Log.e("TOPIC: ", topic);
Log.e("MESSAGE: ", message);
Log.e("onMessageReceived", "--------------------------------------------");
}
#Override
public void onException(String message) {
// TODO Auto-generated method stub
}
};
mComm.addEventHandler(mHandler);
BroadcastReceiver
class ServiceActionReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(MQTTService2.ON_EXCEPTION)) {
Bundle extras = intent.getExtras();
if (extras != null && extras.containsKey(MQTTService2.MESSAGE_STR))
fireOnException(extras.getString(MQTTService2.MESSAGE_STR));
} else if (action.equals(MQTTService2.ON_MESSAGE_RECEIVED)) {
Bundle extras = intent.getExtras();
if (extras != null && extras.containsKey(MQTTService2.MESSAGE_STR)
&& extras.containsKey(MQTTService2.TOPIC_STR))
fireOnMessageReceived(extras.getString(MQTTService2.TOPIC_STR),
extras.getString(MQTTService2.MESSAGE_STR));
} else if (action.equals(MQTTService2.ON_STATUS_CHANGED)) {
Bundle extras = intent.getExtras();
if (extras.containsKey(MQTTService2.STATUS_CODE)) {
MQTTService2.MQTTConnectionStatus status =
MQTTConnectionStatus.parseCode(extras.getString(MQTTService2.STATUS_CODE));
switch (status) {
case CONNECTED:
fireOnStatusChanged(CommunicatorStatus.DISCONNECTED,
extras.getString(MQTTService2.MESSAGE_STR, ""));
break;
case CONNECTING:
break;
case INITIAL:
break;
case NOTCONNECTED_DATADISABLED:
case NOTCONNECTED_UNKNOWNREASON:
case NOTCONNECTED_USERDISCONNECT:
case NOTCONNECTED_WAITINGFORINTERNET:
fireOnStatusChanged(CommunicatorStatus.DISCONNECTED,
extras.getString(MQTTService2.MESSAGE_STR, ""));
break;
default:
break;
}
}
}
}
}
Method called depending on specific intent filter ( onMessageReceived)
private void fireOnMessageReceived(String topic, String message) {
for (MQTTEventHandler eventHandler : handlers) {
eventHandler.onMessageReceived(topic, message);
}
/* for (Iterator<MQTTEventHandler> it = handlers.iterator(); it.hasNext();) {
it.next().onMessageReceived(topic, message);
}*/
}
It seems the following is causing a mismatch between the Intent being broadcast from your Service, and the IntentFilter set on the BroadcastReceiver.
Intent broadcastIntent = new Intent(CALLBACK_ACTION);
broadcastIntent.setAction(ON_MESSAGE_RECEIVED);
The IntentFilter is set for the CALLBACK_ACTION, and the Intent is being instantiated with that same action, but the second line above is resetting the Intent's action to ON_MESSAGE_RECEIVED, causing it to no longer match the Filter on the BroadcastReceiver.
One possible solution would be to add multiple actions to the IntentFilter, and check the delivered action in the Receiver's onReceive() method to determine how to handle the broadcast.
For example:
IntentFilter filter = new IntentFilter(MQTTService2.ACTION_MESSAGE_RECEIVED);
filter.addAction(MQTTService2.ACTION_OTHER);
Then, in the onReceive() method:
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equals(ACTION_MESSAGE_RECEIVED)) {
...
}
else if(action.equals(ACTION_OTHER)) {
...
}
...
}
You would then instantiate the broadcast Intent with the desired action, and remove the setAction() call afterward:
Intent broadcastIntent = new Intent(MQTTService2.ACTION_MESSAGE_RECEIVED);
...

Categories

Resources