application class return nullpointer - null-pointer

its my AplicationClass ==>
#Override
public void onCreate() {
super.onCreate();
mydRef = FirebaseDatabase.getInstance().getReference();
tipDondur();
}
public static Context context() {
return app.getApplicationContext();
}
public boolean internetAktif() {
final ConnectivityManager connectivityManager = ((ConnectivityManager) app
.getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE));
return connectivityManager.getActiveNetworkInfo() != null &&
connectivityManager.getActiveNetworkInfo().isConnected();
}
and when call to internetAktif function from other class ==>
App app = (App) getApplicationContext();
Log.d("", "İnternet durum: " + app.internetAktif());
send error ==>
Caused by: java.lang.NullPointerException at com.example.ercana.yemekevdefb.App.internetAktif(App.java:38) at com.example.ercana.yemekevdefb.Splash.onCreate(Splash.java:31)
what does it mean? How i solve this problem ?

Related

Getting could not create an native instance of the type 'JumioNetverifyBinding.NetverifyConfiguration' the native class hasn't been loaded exception

I am trying to bind Jumio Natverify library in Xamarin iOS project by creating Objective c library project.
I have crated ApiDefination.cs and Struct.cs file data using sharpie tool. But when I am trying on run it I am getting Could not create an native instance of the type 'JumioNetverifyBinding.NetverifyConfiguration': the native class hasn't been loaded. exception.
ApiDefinition class - ApiDefinition.cs
Struct class - Struct.cs
Called NetverifyViewController from iOS Binding project:
using Foundation;
using JumioNetverifyBinding;
using System;
using UIKit;
namespace JumioNetverifyDemo
{
public partial class ViewController : UIViewController
{
NetverifyViewController netverifyViewController;
public ViewController(IntPtr handle) : base(handle) { }
public override void ViewDidLoad()
{
StartNetverifyButton.TouchUpInside += startNetverify;
}
public void CreateNetverifyController()
{
NetverifyConfiguration config = new NetverifyConfiguration();
config.ApiToken = "My_token_key";
config.ApiSecret = "Secrate_key";
config.DataCenter = JumioDataCenter.Eu;
config.Delegate = new NetverifyViewControllerDelegateHandler(this);
this.netverifyViewController = new NetverifyViewController(config);
}
public void startNetverify(object sender, EventArgs e)
{
this.CreateNetverifyController();
if (this.netverifyViewController != null)
{
this.PresentViewController(netverifyViewController, true, null);
}
else
{
Console.WriteLine("Netverify Mobile SDK : NetverifyViewController is null");
}
}
public void DisplayAlertAsync(string title = "Alert", string message = "")
{
var okAlertController = UIAlertController.Create(title, message, UIAlertControllerStyle.Alert);
okAlertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
PresentViewController(okAlertController, true, null);
}
public class NetverifyViewControllerDelegateHandler : NetverifyViewControllerDelegate
{
private ViewController _viewController;
public NetverifyViewControllerDelegateHandler(ViewController viewController)
{
_viewController = viewController;
}
public override void DidCancelWithError(NetverifyViewController netverifyViewController, NetverifyError error, string scanReference, string accountId)
{
Console.WriteLine("NetverifyViewController did finish initializing, error:" + error.Message);
_viewController.DisplayAlertAsync("Error : " + error.Message);
}
public override void DidFinishWithDocumentData(NetverifyViewController netverifyViewController, NetverifyDocumentData documentData, string scanReference, string accountId, bool authenticationResult)
{
_viewController.DisplayAlertAsync("Scan Reference : " + scanReference);
}
}
}
}
I am looking for anyway to handle this exception and make this library work, if anyone have idea about this? Any help would be appreciated.

WebTestClient used multiple times returns empty body sometimes

not sure, why this could be an issue, but I can't stabilize my unit-tests.
Here some snippets from my testclass:
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { "spring.main.web-application-type=reactive" })
#RunWith(SpringRunner.class)
#TestPropertySource(locations = "classpath:application-test.properties")
public class SolrControllerV1Test {
#Inject
ApplicationContext context;
#LocalServerPort
int port;
private WebTestClient client;
#TestConfiguration
static class TestConfig {
#Bean
public TestingAuthenticationProvider testAuthentiationManager() {
return new TestingAuthenticationProvider();
}
#Bean
public SecurityWebFilterChain securityConfig(ServerHttpSecurity http, ReactiveAuthenticationManager authenticationManager) {
AuthenticationWebFilter webFilter = new AuthenticationWebFilter(authenticationManager);
return http.addFilterAt(webFilter, SecurityWebFiltersOrder.AUTHENTICATION)
.authorizeExchange()
.anyExchange()
.authenticated()
.and()
.build();
}
}
#Before
public void setUp() {
this.client = WebTestClient.bindToApplicationContext(context).configureClient().responseTimeout(Duration.ofDays(1L)).baseUrl("http://localhost:" + port).build();
}
private void defaultCheck(ResponseSpec spec) {
spec.expectStatus().isOk().expectBody().jsonPath("$.response.numFound").hasJsonPath();
}
#Test
#WithMockUser(roles = { "ADMIN" })
public void simpleUsrSelect() throws Exception {
ResponseSpec spec = this.client.get().uri("/" + serviceVersion + "/usr/select?q=*:*&fq=*:*&fl=USRTYP,USRKEY,USRCID&rows=1&start=10&sort=last_update desc").exchange();
defaultCheck(spec);
}
#Test
#WithMockUser(roles = { "ADMIN" })
public void simpleCvdSelect() throws Exception {
ResponseSpec spec = this.client.get().uri("/" + serviceVersion + "/cvd/select?q=*:*&rows=10000").exchange();
defaultCheck(spec);
}
.
.
.
}
There are some more unit-tests there, some of which are long running (>1sec). If I have enough unit-tests in the class (~5-8), of which 1 or 2 are taking a bit longer, the unit-tests start to break. This looks like a thread safety issue, but I don't know, what I'm doing wrong. Any ideas?
EDIT
Here the Server Part that made trouble:
#PreAuthorize("hasAnyRole('ADMIN','TENANT')")
public Mono<ServerResponse> select(ServerRequest request) {
return request.principal().flatMap((principal) -> {
return client.get().uri(f -> {
URI u = f.path(request.pathVariable("collection")).path("/select/").queryParams(
queryModifier.modify(principal, request.pathVariable("collection"), request.queryParams())
.onErrorMap(NoSuchFieldException.class, t -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Collection not found"))
.block()).build();
return u;
})
.exchange()
.flatMap((ClientResponse mapper) -> {
return ServerResponse.status(mapper.statusCode())
.headers(c -> mapper.headers().asHttpHeaders().forEach((name, value) -> c.put(name, value)))
.body(mapper.bodyToFlux(DataBuffer.class), DataBuffer.class);
})
.doOnError(t -> handleAuthxErrors(t, principal, request.uri()));
});
}
If I add a publishOn(Schedulers.elastic) right after the .exchange() part, it seems to be working. Since this is trial&error, and I don't really understand why the publishOn fixes the problem, does anybody else know? I'm not even sure, whether using springs reactive Webclient is blocking in this case, or not...
Thanks, Henning

Pending Intent not triggering Intent Service in Geofencing

I am using an intent service to create a notification when user enters in the defined geofenced area.The problem is that when I first run the application it works fine and I am getting the pending-intent on my Intent Service, but after some days(2-3), I am not getting the required intent on the Intent Service.
I have no clue why it stopped working after some days. If I launch the application, it will start normally again but then stopped again after some days.
Here is my activity code --
public class MainActivity extends AppCompatActivity implements View.OnClickListener, GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks, ResultCallback, OnRequestPermissionsResultCallback {
GoogleApiClient mGoogleApiClient;
Location mGeoLocation;
Geofence mGeofence;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}, 100);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mGeoLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
mGoogleApiClient.connect();
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
#Override
public void onClick(View v) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Toast.makeText(MainActivity.this,"",Toast.LENGTH_SHORT);
Log.e("Here I am","Using geofencing in my mobile on 'onConnectionFailed' of main activity");
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (mGeoLocation != null) {
mGeofence = new Geofence.Builder()
.setRequestId("Appstudioz")
.setCircularRegion(mGeoLocation.getLatitude(), mGeoLocation.getLongitude(), 100)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
.build();
mGoogleApiClient.connect();
Intent intent = new Intent(this, MyIntentServiceGeoFencing.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofence(mGeofence);
LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, builder.build(), pendingIntent).setResultCallback(this);
}
}
#Override
public void onConnectionSuspended(int i) {
Log.e("Here I am","Using geofencing in my mobile 'onConnectionSuspended' of main activity");
}
#Override
public void onResult(#NonNull Result result) {
Log.e("Here I am","Using geofencing in my mobile 'onResult' of main activity");
}
}
And this is my Intent Service --
public class MyIntentServiceGeoFencing extends IntentService {
public MyIntentServiceGeoFencing() {
super("MyIntentServiceGeoFencing");
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
String message="";
Log.e("Here I am","Using geofencing in my mobile 'In intent Service'");
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if(geofencingEvent.getGeofenceTransition()== Geofence.GEOFENCE_TRANSITION_ENTER)
{
message="Entering Appstudioz";
}
else if(geofencingEvent.getGeofenceTransition()== Geofence.GEOFENCE_TRANSITION_EXIT)
{
message="Exiting Appstudioz";
}
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.cast_ic_notification_small_icon)
.setContentTitle("Geofence Notification")
.setContentText(message);
// Sets an ID for the notification
int mNotificationId = 001;
// Gets an instance of the NotificationManager service
NotificationManager mNotifyMgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// Builds the notification and issues it.
mNotifyMgr.notify(mNotificationId, mBuilder.build());
if(message.equals("Entering Appstudioz")) {
((AudioManager) getSystemService(AUDIO_SERVICE)).setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
}
else
{
((AudioManager) getSystemService(AUDIO_SERVICE)).setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
}
}
}
I have found my solution. Following are the reasons why the App was not getting Pending Intents according to the official google documentation -
1.The device is rebooted.
2.The app is uninstalled and re-installed.
3.The app's data is cleared.
4.Google Play services data is cleared.
5.The app has received a GEOFENCE_NOT_AVAILABLE alert.(When Android Location Provider(GPS) gets switched off)
You have to re-register the geofence after these events.
In my case device rebooting and location provider(GPS) getting switched off, were the reasons for not getting the pending intents.
Service will stop running when you kill your application, So, you can use broadcast receiver to fix this problem
public class GeofenceReceiver extends BroadcastReceiver
implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
ResultCallback<Status>{
GoogleApiClient mGoogleApiClient;
PendingIntent mGeofencePendingIntent ;
Context mContext;
#Override
public void onReceive(Context context, Intent intent) {
mContext = context;
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addOnConnectionFailedListener(this)
.addConnectionCallbacks(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
try {
LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
// The GeofenceRequest object.
getGeofencingRequest(),
getGeofencePendingIntent()
).setResultCallback(this); // Result processed in onResult().
} catch (SecurityException securityException) {
Log.i(getClass().getSimpleName(),securityException.getMessage());
}
}
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
/**
* Runs when the result of calling addGeofences() and removeGeofences() becomes available.
* Either method can complete successfully or with an error.
*
* Since this activity implements the {#link ResultCallback} interface, we are required to
* define this method.
*
* #param status The Status returned through a PendingIntent when addGeofences() or
* removeGeofences() get called.
*/
#Override
public void onResult(#NonNull Status status) {
if (status.isSuccess()) {
Log.i(getClass().getSimpleName(),"Success");
} else {
// Get the status code for the error and log it using a user-friendly message.
Log.i(getClass().getSimpleName(),getErrorString(status.getStatusCode()));
}
}
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER | GeofencingRequest.INITIAL_TRIGGER_DWELL);
builder.addGeofences(getGeofecne());
return builder.build();
}
private List<Geofence> getGeofecne(){
List<Geofence> mGeofenceList = new ArrayList<>();
//add one object
mGeofenceList.add(new Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId("key")
// Set the circular region of this geofence.
.setCircularRegion(
25.768466, //lat
47.567625, //long
50) // radios
// Set the expiration duration of the geofence. This geofence gets automatically
// removed after this period of time.
//1000 millis * 60 sec * 5 min
.setExpirationDuration(1000 * 60 * 5)
// Set the transition types of interest. Alerts are only generated for these
// transition. We track entry and exit transitions in this sample.
.setTransitionTypes(
Geofence.GEOFENCE_TRANSITION_DWELL)
//it's must to set time in millis with dwell transition
.setLoiteringDelay(3000)
// Create the geofence.
.build());
return mGeofenceList;
}
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(mContext, GeofenceTransitionsIntentService.class);
return PendingIntent.getService(mContext, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
}
}
and here your notification service
public class GeofenceTransitionsIntentService extends IntentService {
protected static final String TAG = "GeofenceTransitionsIS";
/**
* This constructor is required, and calls the super IntentService(String)
* constructor with the name for a worker thread.
*/
public GeofenceTransitionsIntentService() {
// Use the TAG to name the worker thread.
super(TAG);
}
/**
* Handles incoming intents.
* #param intent sent by Location Services. This Intent is provided to Location
* Services (inside a PendingIntent) when addGeofences() is called.
*/
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
Log.e(TAG, getErrorString(geofencingEvent.getErrorCode()));
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL) {
// Get the transition details as a String.
String geofenceTransitionDetails = "Discount 10% for you";
// Send notification and log the transition details.
sendNotification(geofenceTransitionDetails);
Log.i(TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.e(TAG, getString(R.string.geofence_transition_invalid_type + geofenceTransition));
}
}
public static String getErrorString(int errorCode) {
switch (errorCode) {
case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
return "not Available";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
return "Too many Geofences";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return "Too many Pending Intents";
default:
return "unknown geofence error";
}
}
/**
* Posts a notification in the notification bar when a transition is detected.
* If the user clicks the notification, control goes to the MainActivity.
*/
private void sendNotification(String notificationDetails) {
// Create an explicit content Intent that starts the main Activity.
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
// Construct a task stack.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Add the main Activity to the task stack as the parent.
stackBuilder.addParentStack(MainActivity.class);
// Push the content Intent onto the stack.
stackBuilder.addNextIntent(notificationIntent);
// Get a PendingIntent containing the entire back stack.
PendingIntent notificationPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Get a notification builder that's compatible with platform versions >= 4
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Define the notification settings.
builder.setSmallIcon(R.drawable.common_google_signin_btn_icon_dark_normal)
// In a real app, you may want to use a library like Volley
// to decode the Bitmap.
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.drawable.cast_abc_scrubber_primary_mtrl_alpha))
.setColor(Color.RED)
.setContentTitle(notificationDetails)
.setContentText(getString(R.string.geofence_transition_notification_text))
.setContentIntent(notificationPendingIntent);
// Dismiss notification once the user touches it.
builder.setAutoCancel(true);
// Get an instance of the Notification manager
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Issue the notification
mNotificationManager.notify(0, builder.build());
}
}
for more information check out my repo there is full example
https://github.com/3zcs/Geofence

Auto connecting to a BLE device

I am working on an application to coommunicate against a BLE device, currently I am trying to create a Service that starts with the application and auto connect to TI's CC2541 keyfob.
Problem is the gatt server seem to fail EVERY TIME....
I have no clue whats wrong with my code since by google API's and some tutorials I saw
It seems that all the pieces are in their place, yet still nothing works... =(
Here is my service -
package com.example.bluetoothgatt;
import java.util.UUID;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
public class BLE extends Service implements BluetoothAdapter.LeScanCallback {
private final IBinder mBinder = new BluetoothLeBinder();
private final static String TAG = "BLE";
private static final String DEVICE_NAME = "Keyfobdemo";
private BluetoothManager mBluetoothManager;
public BluetoothGatt mConnectedGatt;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice mDevice;
private String mDeviceAddress;
private int mConnectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
/*******************************
*******************************
****** Service Inherited ****** Methods **********
*******************************/
#Override
public void onCreate() {
super.onCreate();
mBluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
Thread discoverDevices = new Thread(mStartRunnable);
discoverDevices.setPriority(discoverDevices.MAX_PRIORITY);
discoverDevices.start();
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
// Implements callback methods for GATT events that the app cares about.
// For example, connection change and services discovered.
private final BluetoothGattExecutor mExecutor = new BluetoothGattExecutor() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
mConnectionState = STATE_CONNECTED;
mConnectedGatt = gatt;
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
}
};
/**
* Return a reference for the current class
*/
public class BluetoothLeBinder extends Binder {
BLE getService() {
return BLE.this;
}
}
private Runnable mStartRunnable = new Runnable() {
#Override
public void run() {
startScan();
}
};
private void startScan() {
if (mConnectionState == STATE_DISCONNECTED) {
mBluetoothAdapter.startLeScan(this);
mHandler.postDelayed(mStopRunnable, 2500);
}
}
private Runnable mStopRunnable = new Runnable() {
#Override
public void run() {
stopScan();
}
};
private void stopScan() {
mBluetoothAdapter.stopLeScan(this);
}
#Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
/*
* We are looking for SensorTag devices only, so validate the name that
* each device reports before adding it to our collection
*/
if (DEVICE_NAME.equals(device.getName())) {
mDevice = device;
mDeviceAddress = mDevice.getAddress();
connect(mDeviceAddress);
mConnectionState = STATE_CONNECTING;
if(device.getBondState() == BluetoothDevice.BOND_BONDED) {
} else if (device.getBondState() == BluetoothDevice.BOND_BONDING) {
} else if(device.getBondState() == BluetoothDevice.BOND_NONE) {
connect(device.getAddress());
}
}
}
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* #param address
* The device address of the destination device.
*
* #return Return true if the connection is initiated successfully. The
* connection result is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG,
"BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mDeviceAddress != null && address.equals(mDeviceAddress)
&& mConnectedGatt != null) {
Log.d(TAG,
"Trying to use an existing BluetoothGatt for connection.");
if (mConnectedGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter
.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device, so we are setting the
// autoConnect
// parameter to false.
mConnectedGatt = device.connectGatt(this, false, mExecutor);
Log.d(TAG, "Trying to create a new connection.");
mDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The
* disconnection result is reported asynchronously through the
* BluetoothGattCallback >>
* onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mConnectedGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mConnectedGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure
* resources are released properly.
*/
public void close() {
if (mConnectedGatt == null) {
return;
}
mConnectedGatt.close();
mConnectedGatt = null;
}
private final UUID IMMEDIATE_ALERT_UUID = UUID
.fromString("00001802-0000-1000-8000-00805f9b34fb");
private final UUID ALERT_LEVEL_UUID = UUID
.fromString("00002a06-0000-1000-8000-00805f9b34fb");
public void Buzz(BluetoothGatt gatt, int level) {
BluetoothGattService alertService = gatt
.getService(IMMEDIATE_ALERT_UUID);
if (alertService == null) {
Log.d(TAG, "Immediate Alert service not found!");
return;
}
BluetoothGattCharacteristic alertLevel = alertService
.getCharacteristic(ALERT_LEVEL_UUID);
if (alertLevel == null) {
Log.d(TAG, "Alert Level charateristic not found!");
return;
}
alertLevel.setValue(level, BluetoothGattCharacteristic.FORMAT_UINT8, 0);
gatt.writeCharacteristic(alertLevel);
Log.d(TAG, "Alert");
}
private final UUID BATTERY_SERVICE_UUID = UUID
.fromString("0000180F-0000-1000-8000-00805f9b34fb");
private final UUID BATTERY_LEVEL_UUID = UUID
.fromString("00002a19-0000-1000-8000-00805f9b34fb");
public int getbattery(BluetoothGatt mBluetoothGatt) {
BluetoothGattService batteryService = mConnectedGatt
.getService(BATTERY_SERVICE_UUID);
if (batteryService == null) {
Log.d(TAG, "Battery service not found!");
return 0;
}
BluetoothGattCharacteristic batteryLevel = batteryService
.getCharacteristic(BATTERY_LEVEL_UUID);
if (batteryLevel == null) {
Log.d(TAG, "Battery level not found!");
return 0;
}
mBluetoothGatt.readCharacteristic(batteryLevel);
return batteryLevel.getIntValue(
BluetoothGattCharacteristic.FORMAT_SINT8, 0);
}
/*
* We have a Handler to process event results on the main thread
*/
private static final int MSG_PROGRESS = 201;
private static final int MSG_DISMISS = 202;
private static final int MSG_CLEAR = 301;
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
BluetoothGattCharacteristic characteristic;
switch (msg.what) {
case MSG_PROGRESS:
break;
case MSG_DISMISS:
break;
case MSG_CLEAR:
break;
}
}
};
public void MakeBuzz() {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
mConnectedGatt = mDevice.connectGatt(getApplicationContext(),
true, mExecutor);
BluetoothGattService alertService = mConnectedGatt
.getService(IMMEDIATE_ALERT_UUID);
int x = getbattery(mConnectedGatt);
Buzz(mConnectedGatt, 2);
}
});
t.start();
}
}
This it the Application class -
package com.example.bluetoothgatt;
import android.app.Application;
import android.content.Intent;
public class ApplicationBleTest extends Application {
// Application variables
public final String SMOKE_TALK_PACKAGE_NAME = "com.smoketalk";
private BluetoothLEService mBleService;
private static int MODE_PRIVATE;
/**
* Application OnCreate event initiate the class parameters
*/
public void onCreate() {
super.onCreate();
getApplicationContext().startService(new Intent(this, BLE.class));
}
}
And this is the main activity (I am trying to make the keyfob alaram buzz on a button click)
package com.example.bluetoothgatt;
import com.example.bluetoothgatt.BluetoothLowEnergyService.BluetoothLeBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
* Created by Dave Smith Double Encore, Inc. MainActivity
*/
public class MainActivity extends Activity {
BluetoothLowEnergyService mBluetoothService;
boolean isBound = false;
Button buzz;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, BluetoothLowEnergyService.class);
bindService(intent, mBleServiceConnection, Context.BIND_AUTO_CREATE);
buzz = (Button) findViewById(R.id.btn1);
buzz.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mBluetoothService.MakeBuzz();
}
});
}
private ServiceConnection mBleServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
BluetoothLeBinder binder = (BluetoothLeBinder) service;
mBluetoothService = binder.getService();
isBound = true;
}
public void onServiceDisconnected(ComponentName arg0) {
isBound = false;
}
};
}
And the menifest file -
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bluetoothgatt"
android:versionCode="1"
android:versionName="1.0" >
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<uses-sdk
android:minSdkVersion="18"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED"/>
<application
android:name="com.example.bluetoothgatt.ApplicationBleTest"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="SensorTag Weather" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.example.bluetoothgatt.BLE" />
</application>
</manifest>
and last one the layout for the main activity -
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="#dimen/activity_horizontal_margin"
android:text="Android BLE Test"
android:textSize="42sp" />
<Button
android:id="#+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_centerHorizontal="true"
android:layout_marginTop="56dp"
android:text="Buzz" />
</RelativeLayout>
ANY help will be appreciated since I rellay have no clue what goes wrong... =(
For starters, I would recommend commenting out the bond code (Everything after if(device.getBondState().. in the onLeScan method) The whole bonding process was unstable on 4.3 (Nexus devices at least) and became more stable on 4.4.
You should be able to discover devices, and with the BluetoothDevice the user selects you should call ConnectGatt after stopping discovery. This will attempt to connect to the Gatt server on the device. If the connection is successful, you should receive a callback on your connectionStateChange indicating that the connection was successful.
The concept behind bonding is related to pairing with the device and exchanging keys if your characteristics are encrypted. Normally you should be able to connect to the Gatt server without needing to bond, but once you are connected, if you do try to read an encrypted characteristic, it will fail.
I tried your code and it works. you need to follow this process:
BluetoothAdapter.startLeScan(leCallback)
In the onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) in leCallback, call btDevice.connectGatt(Context context, Boolean autoConnect, BluetoothGattCallback gattCallback);
In the onConnectionStateChange(BluetoothGatt gatt, int status, int newState) in gattCallBack, check if newState is BluetoothProfile.STATE_CONNECTED, if yes, call gatt.discoverServices();
In the onServicesDiscovered(BluetoothGatt gatt, int status) in gattCallBack, check if status is BluetoothGatt.GATT_SUCCESS, if yes, get the service by UUID like this: BluetoothGattService service = gatt.getService(YOUR_SERVICE_UUID);
If the service is null, it means the service has not yet been discovered, you need to check again when the next service is discovered and the onServicesDiscovered will be called again.
By the time all the services has been discovered, you should already got your service, unless the device does not support it.
Now you can use your service in your Buzz method.
Also worth noting is that the BLE actions must all be serialized by you. Eg, if you made a read/write to a characteristic you need to wait for the callback before doing another. If not, this will result in an error.
Since you are running from a service you can try running connect on the main thread like this:
public void connectToDevice( String deviceAddress) {
mDeviceAddress = deviceAddress;
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(mDeviceAddress);
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
if (device != null) {
mGatt = device.connectGatt(getApplicationContext(), true, mGattCallback);
scanLeDevice(false);// will stop after first device detection
}
}
});
}
Hope it helps.

Developing Hive UDAF meet a ClassCastException without an idea

`public class GenericUdafMemberLevel implements GenericUDAFResolver2 {
private static final Log LOG = LogFactory
.getLog(GenericUdafMemberLevel.class.getName());
#Override
public GenericUDAFEvaluator getEvaluator(GenericUDAFParameterInfo paramInfo)
throws SemanticException {
return new GenericUdafMeberLevelEvaluator();
}
#Override
//参数校验
public GenericUDAFEvaluator getEvaluator(TypeInfo[] parameters)
throws SemanticException {
if (parameters.length != 2) {//参数大小
throw new UDFArgumentTypeException(parameters.length - 1,
"Exactly two arguments are expected.");
}
//参数必须是原型,即不能是
if (parameters[0].getCategory() != ObjectInspector.Category.PRIMITIVE) {
throw new UDFArgumentTypeException(0,
"Only primitive type arguments are accepted but "
+ parameters[0].getTypeName() + " is passed.");
}
if (parameters[1].getCategory() != ObjectInspector.Category.PRIMITIVE) {
throw new UDFArgumentTypeException(1,
"Only primitive type arguments are accepted but "
+ parameters[1].getTypeName() + " is passed.");
}
return new GenericUdafMeberLevelEvaluator();
}
public static class GenericUdafMeberLevelEvaluator extends GenericUDAFEvaluator {
private PrimitiveObjectInspector inputOI;
private PrimitiveObjectInspector inputOI2;
private DoubleWritable result;
#Override
public ObjectInspector init(Mode m, ObjectInspector[] parameters)
throws HiveException {
super.init(m, parameters);
if (m == Mode.PARTIAL1 || m == Mode.COMPLETE){
inputOI = (PrimitiveObjectInspector) parameters[0];
inputOI2 = (PrimitiveObjectInspector) parameters[1];
result = new DoubleWritable(0);
}
return PrimitiveObjectInspectorFactory.writableLongObjectInspector;
}
/** class for storing count value. */
static class SumAgg implements AggregationBuffer {
boolean empty;
double value;
}
#Override
//创建新的聚合计算的需要的内存,用来存储mapper,combiner,reducer运算过程中的相加总和。
//使用buffer对象前,先进行内存的清空——reset
public AggregationBuffer getNewAggregationBuffer() throws HiveException {
SumAgg buffer = new SumAgg();
reset(buffer);
return buffer;
}
#Override
//重置为0
//mapreduce支持mapper和reducer的重用,所以为了兼容,也需要做内存的重用。
public void reset(AggregationBuffer agg) throws HiveException {
((SumAgg) agg).value = 0.0;
((SumAgg) agg).empty = true;
}
private boolean warned = false;
//迭代
//map阶段调用,只要把保存当前和的对象agg,再加上输入的参数,就可以了。
#Override
public void iterate(AggregationBuffer agg, Object[] parameters)
throws HiveException {
// parameters == null means the input table/split is empty
if (parameters == null) {
return;
}
try {
double flag = PrimitiveObjectInspectorUtils.getDouble(parameters[1], inputOI2);
if(flag > 1.0) //参数条件
merge(agg, parameters[0]); //这里将Map之后的操作,放入combiner进行合并
} catch (NumberFormatException e) {
if (!warned) {
warned = true;
LOG.warn(getClass().getSimpleName() + " "
+ StringUtils.stringifyException(e));
}
}
}
#Override
//combiner合并map返回的结果,还有reducer合并mapper或combiner返回的结果。
public void merge(AggregationBuffer agg, Object partial)
throws HiveException {
if (partial != null) {
//通过ObejctInspector取每一个字段的数据
double p = PrimitiveObjectInspectorUtils.getDouble(partial, inputOI);
((SumAgg) agg).value += p;
}
}
#Override
//reducer返回结果,或者是只有mapper,没有reducer时,在mapper端返回结果。
public Object terminatePartial(AggregationBuffer agg)
throws HiveException {
return terminate(agg);
}
#Override
public Object terminate(AggregationBuffer agg) throws HiveException {
result.set(((SumAgg) agg).value);
return result;
}
}
}`
I have used some chinese to comment the code for understanding the theory.
Actually, the idea of the UDAF is like follow:
select test_sum(col1,col2) from tbl ;
if col2 satisfy some condition, then sum col1's value.
Most of the code are copied from the offical avg() udaf function.
I met a weried Exception:
java.lang.RuntimeException: Hive Runtime Error while closing operators
at org.apache.hadoop.hive.ql.exec.ExecMapper.close(ExecMapper.java:226)
at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:57)
at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:436)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:372)
at org.apache.hadoop.mapred.Child$4.run(Child.java:255)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:396)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1136)
at org.apache.hadoop.mapred.Child.main(Child.java:249)
Caused by: org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.ClassCastException: org.apache.hadoop.io.DoubleWritable cannot be cast to org.apache.hadoop.io.LongWritable
at org.apache.hadoop.hive.ql.exec.GroupByOperator.closeOp(GroupByOperator.java:1132)
at org.apache.hadoop.hive.ql.exec.Operator.close(Operator.java:558)
at org.apache.hadoop.hive.ql.exec.Operator.close(Operator.java:567)
at org.apache.hadoop.hive.ql.exec.Operator.close(Operator.java:567)
at org.apache.hadoop.hive.ql.exec.Operator.close(Operator.java:567)
at org.apache.hadoop.hive.ql.exec.ExecMapper.close(ExecMapper.java:193)
... 8 more
Caused by: java.lang.ClassCastException: org.apache.hadoop.io.DoubleWritable cannot be cast to org.apache.hadoop.io.LongWritable
at org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableLongObjectInspector.get(WritableLongObjectInspector.java:35)
at org.apache.hadoop.hive.serde2.lazybinary.LazyBinarySerDe.serialize(LazyBinarySerDe.java:323)
at org.apache.hadoop.hive.serde2.lazybinary.LazyBinarySerDe.serializeStruct(LazyBinarySerDe.java:255)
at org.apache.hadoop.hive.serde2.lazybinary.LazyBinarySerDe.serialize(LazyBinarySerDe.java:202)
at org.apache.hadoop.hive.ql.exec.ReduceSinkOperator.processOp(ReduceSinkOperator.java:236)
at org.apache.hadoop.hive.ql.exec.Operator.process(Operator.java:474)
at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:800)
at org.apache.hadoop.hive.ql.exec.GroupByOperator.forward(GroupByOperator.java:1061)
at org.apache.hadoop.hive.ql.exec.GroupByOperator.closeOp(GroupByOperator.java:1113)
... 13 more
Am I have something wrong with my UDAF??
please kindly point it out.
Thanks a lllllllot .
Replace PrimitiveObjectInspectorFactory.writableLongObjectInspector in init method with PrimitiveObjectInspectorFactory.writableDoubleObjectInspector.