I tried to change database onDisconnect method.
I want to change the database when connectivity available from background.
For example,
Suppose currently i am in MainActivity and status is Online and in onPause and onDestroy it becomes offline. For my side it is not enough to set online/offline status.
For this i want
if i have connectivity (background and foreground) my status
is online
if i lost connectivity in the BACKGROUND, my status is offline. And whenever connectivity is available and app is in killed Mode, my status is online.
For this solution stackoverflow suggests me to use BroadCastReceiver, but i dont know how to use this class
We can easily do it by using a Service and a Broadcast Receiver simultaneously to get the output as you wish. This will work always i.e when app is running, app is minimized or when app is even removed from minimized apps.
1.Manifest Code :
<application
...
<service android:name=".MyService" />
</application>
2.MyService.java
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
static final String CONNECTIVITY_CHANGE_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
NotificationManager manager ;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (CONNECTIVITY_CHANGE_ACTION.equals(action)) {
//check internet connection
if (!ConnectionHelper.isConnectedOrConnecting(context)) {
if (context != null) {
boolean show = false;
if (ConnectionHelper.lastNoConnectionTs == -1) {//first time
show = true;
ConnectionHelper.lastNoConnectionTs = System.currentTimeMillis();
} else {
if (System.currentTimeMillis() - ConnectionHelper.lastNoConnectionTs > 1000) {
show = true;
ConnectionHelper.lastNoConnectionTs = System.currentTimeMillis();
}
}
if (show && ConnectionHelper.isOnline) {
ConnectionHelper.isOnline = false;
Log.i("NETWORK123","Connection lost");
//manager.cancelAll();
}
}
} else {
Log.i("NETWORK123","Connected");
showNotifications("APP" , "It is working");
// Perform your actions here
ConnectionHelper.isOnline = true;
}
}
}
};
registerReceiver(receiver,filter);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
}
3.ConnectionHelper.java
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public class ConnectionHelper {
public static long lastNoConnectionTs = -1;
public static boolean isOnline = true;
public static boolean isConnected(Context context) {
ConnectivityManager cm =(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnected();
}
public static boolean isConnectedOrConnecting(Context context) {
ConnectivityManager cm =(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
}
}
4.Your Activity Code
startService(new Intent(getBaseContext(), MyService.class));
With this code, you will be able to check the connectivity when the app is onStart, On pause and even when the app is destroyed
You can use this method. It works fine for me.
DatabaseReference connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
Log.d("FirasChebbah", "connected");
} else {
Log.d("FirasChebbah", "not connected");
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.w("FirasChebbah", "Listener was cancelled");
}
});
Related
I am trying to scan Wifi every 10 seconds. I have produced an Android Foreground service to achieve this. The application has all of the right permissions and does get the list of local Wifi hotspots. However, it does this once. I have tried to implement a thread to do this every 10 seconds, as can be seen in the code below. The Log.d() message is logged every 10 seconds but the Wifi is not printed after the first time it is printed.
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class ForegroundService extends Service {
private WifiManager wifiManager;
public static final String CHANNEL_ID = "ForegroundServiceChannel";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_stat_name)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
//do heavy work on a background thread
wifiManager = (WifiManager) getApplicationContext().getSystemService(getApplicationContext().WIFI_SERVICE);
if (!wifiManager.isWifiEnabled()) {
//Toast.makeText(this, "WiFi is disabled ... We need to enable it", Toast.LENGTH_LONG).show();
wifiManager.setWifiEnabled(true);
}
registerReceiver(wifiReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
new Thread(new Runnable() {
#Override
public void run() {
Looper.prepare();
while (true) {
Log.d("Test","00000000000000");
scanWifi();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//stopSelf();
return START_NOT_STICKY;
}
private void scanWifi() {
wifiManager.startScan();
Toast.makeText(this, "Scanning WiFi ...", Toast.LENGTH_SHORT).show();
}
BroadcastReceiver wifiReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
List<ScanResult> results = wifiManager.getScanResults();
unregisterReceiver(this);
for (ScanResult scanResult : results) {
Log.d("WIFI",scanResult.SSID + " - " + scanResult.capabilities);
}
}
};
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
I think you should remove unregisterReceiver(this); from onRecieve and place it onDestroy()
public class NetworkStateChecker {
public static int TYPE_WIFI = 1;
public static int TYPE_MOBILE = 2;
public static int TYPE_NOT_CONNECTED = 0;
public static int getConnectivityStatus(Context context) {
try {
TimeUnit.SECONDS.sleep(10); // Sleeps 10 seconds.
} catch (InterruptedException e) {
e.printStackTrace();
}
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork!=null) {
if(activeNetwork.getType() == ConnectivityManager.TYPE_WIFI)
return TYPE_WIFI;
if(activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE)
return TYPE_MOBILE;
}
return TYPE_NOT_CONNECTED;
}
public static String getConnectivityStatusString(Context context) {
int conn = NetworkStateChecker.getConnectivityStatus(context);
String status = null;
if (conn == NetworkStateChecker.TYPE_WIFI) {
status = "Wifi enabled";
} else if (conn == NetworkStateChecker.TYPE_MOBILE) {
status = "Mobile data enabled";
} else if (conn == NetworkStateChecker.TYPE_NOT_CONNECTED) {
status = "Not connected to Internet";
}
return status;
}
}
use the above class to check the available network connections for every 10sec...
Next in broadcase reciever tyr the below code
String status = NetworkStateChecker.getConnectivityStatusString(context);
use the below permissions
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
..............
<receiver
android:name="in.phoenix.services.NetworkChangeReceiver"
android:label="NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
</intent-filter>
</receiver>
I'm working on an application to communicate with a raspberry pi. The app communicates with the server via a socket connection.
I'm currently able to building up the communication and holding it in a service. But my goal is to change from activity A to activity B. The problem is, that my application destroys the service when im switching the activities. Is there a way to avoid this?
Activity A starts the service and when im starting Activity B i bind it to the activity to call the methods in the service class. But it isn't the same instance.
How could i solve this?
Code
ConnectActivity
package com.example.domen.twitchdronev3;
import android.content.Intent;
import android.os.Parcelable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class ConnectActivity extends AppCompatActivity {
private int port = 3000;
private String ip = "localhost";
private Intent serviceIntent, activityIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_connect);
Toast.makeText(getApplicationContext(), "Starte App...", Toast.LENGTH_LONG).show();
activityIntent = new Intent(this, ControllActivity.class);
serviceIntent = new Intent(this, ClientService.class);
serviceIntent.putExtra("ip", ip);
serviceIntent.putExtra("port", port);
Button btnActivity = (Button) findViewById(R.id.changeActivity);
btnActivity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startService(serviceIntent);
activityIntent.putExtra("Intent", (Parcelable) serviceIntent);
startActivity(activityIntent);
}
});
}
// destroys the Activity
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getApplicationContext(), "Destroy (ConnectActivity)", Toast.LENGTH_LONG).show();
}
// Activity stopping
#Override
protected void onStop() {
super.onStop();
}
}
ControllActivity
package com.example.domen.twitchdronev3;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class ControllActivity extends AppCompatActivity {
public static final String TAG = "ControllActivity";
private ClientService clientservice;
private Intent serviceIntent;
private boolean isBound;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_controll);
Bundle extras = getIntent().getExtras();
serviceIntent = extras.getParcelable("Intent");
Button btnDisconnect = (Button) findViewById(R.id.btnDisconnect);
btnDisconnect.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
doBindToService();
}
});
}
// destroys the Activity
#Override
public void onDestroy(){
super.onDestroy();
Toast.makeText(getApplicationContext(), "Destroy (ControllActivity)", Toast.LENGTH_LONG).show();
doUnbindToService();
stopService(serviceIntent);
}
// Functions to BIND and UNBIND the SERVICE
// bind to Service
public void doBindToService(){
if(!isBound) {
Toast.makeText(this, "(doBindToService) Binding...", Toast.LENGTH_LONG).show();
isBound = bindService(serviceIntent, myConnection, Context.BIND_AUTO_CREATE);
}
}
// Unbind to Service
public void doUnbindToService(){
Toast.makeText(this, "(doUnbindToService) Unbinding...", Toast.LENGTH_LONG).show();
unbindService(myConnection);
isBound = false;
}
private ServiceConnection myConnection = new ServiceConnection(){
public static final String TAG = "ConnectActivity";
#Override
public void onServiceConnected(ComponentName className, IBinder service){
Log.i(TAG, "BOUND SERVICE CONNECTED");
clientservice = ((ClientService.ClientBinder) service).getService();
isBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name){
Log.i(TAG, "BOUND SERVICE DISCONNECTED");
clientservice = null;
isBound = false;
}
};
}
ClientService
package com.example.domen.twitchdronev3;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
/**
* Created by ViTrex on 12.02.2018.
*/
public class ClientService extends Service {
private static final String TAG = "ClientService";
private final IBinder mBinder = new ClientBinder();
private PrintWriter out;
private Socket socket;
private String ip = "";
private int port = 0;
private Thread backgroundThread;
// the class used for the client binder
public class ClientBinder extends Binder {
ClientService getService() {
// returns the instance of ClientService
// so the client can access the public methods
return ClientService.this;
}
}
//SETTER
public void setIP(String ip) {
this.ip = ip;
}
public void setPort(int port) {
this.port = port;
}
//GETTER
public String getIP() {
return this.ip;
}
public int getPort() {
return this.port;
}
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate...");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "onStartCommand", Toast.LENGTH_LONG).show();
if(intent != null){
setIP(intent.getStringExtra("ip"));
setPort(intent.getIntExtra("port", 3000));
}
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind called...");
Toast.makeText(this, getIP() + " " + getPort(), Toast.LENGTH_LONG).show();
backgroundThread = new Thread(new Runnable() {
#Override
public void run() {
buildConnection();
}
});
backgroundThread.start();
return mBinder;
}
private void buildConnection() {
Log.i(TAG, "Try to build up a connection ...");
synchronized (this) {
try {
this.socket = new Socket(getIP(), getPort());
this.out = new PrintWriter(this.socket.getOutputStream(), true);
Log.i(TAG, "Connected");
} catch (IOException ioe) {
Log.i(TAG, ioe.getMessage());
this.socket = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Close Service");
Thread dummy = backgroundThread;
backgroundThread = null;
if (dummy != null)
dummy.interrupt();
if (this.socket != null) {
try {
this.out.close();
this.socket.close();
Log.i(TAG, "Close Socket");
} catch (IOException ioe) {
Log.i(TAG, "ERROR: Close Socket");
}
}
}
}
You say:
Activity A starts the service and when I'm starting Activity B I bind
it to the activity to call the methods in the service class. But it
isn't the same instance.
How do you know it is not the same instance (presumably you mean of the service instance)?
I think your code is o.k. to run on older devices (It runs o.k. on my device. pre-API26, I think permissions changed after then so maybe more code needed. See NOTE at the end of this answer).
Don't you want START_STICKY ?
I would add this code (read the Intent data that was setup by Activity A) to your ClientService.java:
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
String a_ip = intent.getStringExtra("ip");
int a_port = intent.getIntExtra("port",-1);
Log.i(TAG, "onStartCommand called...with " + "ip:" + a_ip + "and port:"+ a_port);
setIP(a_ip);
setPort(a_port);
return START_NOT_STICKY;//don't you want START_STICKY ?
}
Note: If your app targets API level 26 or higher, the system imposes
restrictions on using or creating background services unless the app
itself is in the foreground. If an app needs to create a foreground
service, the app should call StartForegroundService(). That method
creates a background service, but the method signals to the system
that the service will promote itself to the foreground. Once the
service has been created, the service must call its startForeground()
method within five seconds. From here
I have found this Serial Port example:
MainActivity.java
package com.felhr.serialportexample;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.lang.ref.WeakReference;
import java.util.Set;
public class MainActivity extends AppCompatActivity {
/*
* Notifications from UsbService will be received here.
*/
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;
private 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);
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
usbService = null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new MyHandler(this);
display = (TextView) findViewById(R.id.textView1);
editText = (EditText) findViewById(R.id.editText1);
Button sendButton = (Button) findViewById(R.id.buttonSend);
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!editText.getText().toString().equals("")) {
String data = editText.getText().toString();
if (usbService != null) { // if UsbService was correctly binded, Send data
display.append(data);
usbService.write(data.getBytes());
}
}
}
});
}
#Override
public void onResume() {
super.onResume();
setFilters(); // Start listening notifications from UsbService
startService(UsbService.class, usbConnection, null); // Start UsbService(if it was not started before) and Bind it
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(mUsbReceiver);
unbindService(usbConnection);
}
private void startService(Class<?> service, ServiceConnection serviceConnection, Bundle extras) {
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);
}
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);
}
/*
* This handler will be passed to UsbService. Data received from serial port is displayed through this handler
*/
private static class MyHandler extends Handler {
private final WeakReference<MainActivity> mActivity;
public MyHandler(MainActivity activity) {
mActivity = new WeakReference<>(activity);
}
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UsbService.MESSAGE_FROM_SERIAL_PORT:
String data = (String) msg.obj;
mActivity.get().display.append(data);
break;
}
}
}
}
and UsbService.java
package com.felhr.serialportexample;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import com.felhr.usbserial.CDCSerialDevice;
import com.felhr.usbserial.UsbSerialDevice;
import com.felhr.usbserial.UsbSerialInterface;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
public class UsbService extends Service {
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;
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 Context 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();
}
}
};
/*
* 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);
serialPortConnected = true;
new ConnectionThread().run();
} 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);
serialPortConnected = false;
serialPort.close();
}
}
};
/*
* 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();
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()) {
boolean keep = true;
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)) {
// There is a device connected to our Android device. Try to open it as a Serial Port.
requestUserPermission();
keep = false;
} else {
connection = null;
device = null;
}
if (!keep)
break;
}
if (!keep) {
// There is no USB devices connected (but usb host were listed). Send an intent to MainActivity.
Intent intent = new Intent(ACTION_NO_USB);
sendBroadcast(intent);
}
} else {
// 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() {
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()) {
serialPort.setBaudRate(BAUD_RATE);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
serialPort.read(mCallback);
// 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);
}
}
}
}
In this app you can type a string, send it and it will print it. What I want to do is send that input through an FTDI to a pc where it is visible in PuTTy. I'm new to this so I have no idea where in the code this has to be changed.
It seeems very old but I solved that by adding in Handle message handler case UsbService.SYNC_READ:
and actually i found that data coming from the serial.
I have an Android project in which I use a service in order, I'm currently using this service to watch the MediaPlayer and events go through the BR.
package com.uk.jacob.groovebuddy;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
public class MediaSyncService extends Service {
#Override
public void onCreate() {
super.onCreate();
IntentFilter iF = new IntentFilter();
iF.addAction("com.android.music.metachanged");
iF.addAction("com.htc.music.metachanged");
iF.addAction("fm.last.android.metachanged");
iF.addAction("com.sec.android.app.music.metachanged");
iF.addAction("com.nullsoft.winamp.metachanged");
iF.addAction("com.amazon.mp3.metachanged");
iF.addAction("com.miui.player.metachanged");
iF.addAction("com.real.IMP.metachanged");
iF.addAction("com.sonyericsson.music.metachanged");
iF.addAction("com.rdio.android.metachanged");
iF.addAction("com.samsung.sec.android.MusicPlayer.metachanged");
iF.addAction("com.andrew.apollo.metachanged");
registerReceiver(mReceiver, iF);
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction() != null) {
String track = intent.getStringExtra("track");
String album = intent.getStringExtra("album");
String artist = intent.getStringExtra("artist");
Log.d("Test", "Your listening to " + track + " on the album " + album + " by the artist " + artist);
}
}
};
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed...", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
The broadcast receiver is being triggered twice and as such I see the output
Your listening to After Midnight on the album Neighborhoods (Deluxe Explicit Version) by the artist blink-182
Your listening to After Midnight on the album Neighborhoods (Deluxe Explicit Version) by the artist blink-182
As you can see I am registering the BR only once.
Below is the pictorial of the problem with my app.
THE APP ON STARTUP:
ON 100% PROGRESS:
NOW, IF I HIT BACK KEY AND AGAIN RETURN TO APP:
WHAT I ACTUALLY WANT: app should resume and not reload when the user returns after pressing back key.
I am sharing the code below. Kindly, suggest a solution.
package com.url.app;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.webkit.ValueCallback;
import android.webkit.WebView;
import android.webkit.WebChromeClient;
import android.webkit.WebViewClient;
import android.provider.Settings;
public class MainActivity extends Activity {
private WebView wv;
//make HTML upload button work in Webview
private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE=1;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if(requestCode==FILECHOOSER_RESULTCODE)
{
if (null == mUploadMessage) return;
Uri result = intent == null || resultCode != RESULT_OK ? null
: intent.getData();
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
//Check if user is online
public boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
return true;
}
return false;
}
//if not online show alertdialog with settings button
public void showNoConnectionDialog(Context ctx1) {
final Context ctx = ctx1;
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setCancelable(true);
builder.setMessage(R.string.no_connection);
builder.setTitle(R.string.no_connection_title);
builder.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
ctx.startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
return;
}
});
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
return;
}
});
builder.setCancelable(false);
builder.show();
}
//supress lint coz it cries over javascript enabled
#SuppressLint("SetJavaScriptEnabled") #Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//if not online then show NO CONNECTION Dialog
if(!isOnline()) {
showNoConnectionDialog(MainActivity.this);
}
//webview
wv = new WebView(this);
//loadurl
wv.loadUrl(getString(R.string.siteurl));
//Enable JavaScript
wv.getSettings().setJavaScriptEnabled(true);
//Zoom
wv.getSettings().setBuiltInZoomControls(true);
wv.getSettings().setSupportZoom(true);
//progressdialog
final ProgressDialog pd = ProgressDialog.show(this, "", getString(R.string.loading), true);
pd.setCanceledOnTouchOutside(false);
wv.setWebViewClient(new WebViewClient(){
//hide progressdialog when page loads completely
#Override
public void onPageFinished(WebView view, String url) {
if(pd.isShowing() && pd!=null)
{
pd.dismiss();
}
}
});
wv.setWebChromeClient(new WebChromeClient() {
// For Android 3.0+
public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
MainActivity.this.startActivityForResult( Intent.createChooser( i, getString(R.string.fileselect) ), MainActivity.FILECHOOSER_RESULTCODE );
}
// For Android < 3.0
public void openFileChooser( ValueCallback<Uri> uploadMsg ) {
openFileChooser( uploadMsg, "" );
}
// For Android > 4.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
openFileChooser( uploadMsg, "" );
}
});
setContentView(wv);
}
}
PS: the upload button is working in my code, the problem is how do I keep WebView active in background, such that if user starts uploading and exits the app, uploading continues.
UPDATE: I think overriding the back button along with a notification may be useful in this case.
Catching the back button to behave like home key
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
moveTaskToBack(true);
return true;
}
return super.onKeyDown(keyCode, event);
}