I am integrating the AltBeacon API in an existing app. The app shall start actions in the background, when the user enters or leaves a "bluetooth zone".
This functionality should be optional and the user should start and stop the scanning from the settings.
I tryed bind/unbind the BeaconConsumer, but I saw, that in the background the BluetoothLeScanner is keeping scanning! How can I stop the BluetoothLeScanner from scanning? Is this the right way?
Here is the code:
#Override
public void onCreate() {
super.onCreate();
LogManager.setVerboseLoggingEnabled(true);
log.debug("onCreate");
mAllBeaconsRegion = new Region(ALLBEACONS, null, null, null);
mBeaconManager = BeaconManager.getInstanceForApplication(this);
mBackgroundPowerSaver = new BackgroundPowerSaver(this);
mBeaconManager.setBackgroundBetweenScanPeriod(60000L);
mBeaconManager.setBackgroundScanPeriod(2100L);
// wake up the app when a beacon is seen
mRegionBootstrap = new RegionBootstrap(this, mAllBeaconsRegion);
mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
dsGlobal = new DbGlobalsHelper(getApplicationContext());
boolean isBeaconScan = Utils.isBoolean(dsGlobal.getCursorGlobalsByKey(Constants.DB_KEY_BEACON_SCAN));
if(isBeaconScan){
mBeaconManager.bind(this);
}else{
mBeaconManager.unbind(this);
}
}
// Set Regions to monitor at boot/startup
private void setRegionsAtBoot(){
Log.i(TAG, "setRegionsAtBoot");
log.info("setRegionsAtBoot");
SimpleBeaconStore beaconStore = new SimpleBeaconStore(this);
List<SimpleBeacon> beacons = beaconStore.getBeacons();
for (Iterator<SimpleBeacon> iterator = beacons.iterator(); iterator.hasNext();) {
SimpleBeacon simpleBeacon = iterator.next();
List<Identifier> listB = new ArrayList<Identifier>();
StringTokenizer st = new StringTokenizer(simpleBeacon.getBeaconUuid(), "#");
while (st.hasMoreTokens()) {
listB.add(new Identifier(Identifier.parse(st.nextToken())));
}
try {
Log.i(TAG, "setRegionsAtBoot " + simpleBeacon.getId());
log.info("setRegionsAtBoot " + simpleBeacon.getId());
Region region = new Region(simpleBeacon.getId(), listB);
mBeaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
// Start actions
if (region.getUniqueId().equals(ALLBEACONS)){
return;
}
if (beacons.size() > 0) {
for (Beacon beacon: beacons) {
Log.d(TAG, "Beacon "+beacon.toString()+" is about "+beacon.getDistance()+" meters away, with Rssi: "+beacon.getRssi());
log.debug("Beacon " + beacon.toString() + " is about " + beacon.getDistance() + " meters away, with Rssi: " + beacon.getRssi());
datasource = new DbZoneHelper(getApplicationContext());
ZoneEntity ze = datasource.getCursorZoneByName(region.getUniqueId());
if (beacon.getDistance() < ze.getRadius() && !ze.isStatus()) {
//
Log.i(TAG, "Beacon " + beacon.toString() + " Just became less than " + ze.getRadius() + " meters away.");
log.info("*** Beacon " + beacon.toString() + " Just became less than " + ze.getRadius() + " meters away. ***");
String transitionType = getTransitionString(1);
NotificationUtil.sendNotification(getApplicationContext(), transitionType, region.getUniqueId());
worker = new Worker(getApplicationContext());
worker.handleTransition(1, region.getUniqueId(), Constants.BEACON);
}
if (beacon.getDistance() > (ze.getRadius() * EXITMULTIPLICATOR) && ze.isStatus()) {
//
Log.i(TAG, "Beacon "+ beacon.toString()+" Just became over " + ze.getRadius() * EXITMULTIPLICATOR + " meters away.");
log.info("*** Beacon " + beacon.toString() + " Just became over " + ze.getRadius() * EXITMULTIPLICATOR + " meters away. ***");
String transitionType = getTransitionString(2);
NotificationUtil.sendNotification(getApplicationContext(), transitionType, region.getUniqueId());
worker = new Worker(getApplicationContext());
//
worker.handleTransition(2, region.getUniqueId(), Constants.BEACON);
}
}
}
}
#Override
public void didDetermineStateForRegion(int arg0, Region arg1) {
}
#Override
public void didEnterRegion(Region region) {
}
#Override
public void didExitRegion(Region region) {
if (region.getUniqueId().equals(ALLBEACONS)){
return;
}
datasource = new DbZoneHelper(getApplicationContext());
ZoneEntity ze = datasource.getCursorZoneByName(region.getUniqueId());
if (ze.isStatus()) {
//
Log.i(TAG, "Beacon " + region.getUniqueId() + " Just exited region.");
log.info("Beacon " + region.getUniqueId() + " Just exited region.");
String transitionType = getTransitionString(2);
NotificationUtil.sendNotification(getApplicationContext(), transitionType, region.getUniqueId());
worker = new Worker(getApplicationContext());
worker.handleTransition(2, region.getUniqueId(), Constants.BEACON);
}
}
#Override
public void onBeaconServiceConnect() {
Log.d(TAG, "onBeaconServiceConnect.");
log.debug("onBeaconServiceConnect");
setRegionsAtBoot();
mBeaconManager.setRangeNotifier(this);
}
public void bind(){
mBeaconManager.bind(this);
}
public void unbind(){
mBeaconManager.unbind(this);
}
I am also calling the bind/unbind from my settings.
The code shown uses a RegionBootstrap class to continually scan for beacons in the background. This class is essentially designed to never stop scanning for beacons. The RegionBootstrap binds to the scanning service when constructed and effectively never unbinds. The code shown that manually binds and unbinds therefore has no effect.
If you want to start and stop scanning at various times, then don't use the RegionBootstrap class, and instead make your Application or Activity implement BeaconConsumer and bind/unbind as described in the monitoring example code here: http://altbeacon.github.io/android-beacon-library/samples.html
EDIT: New methods have been added to RegionBootstrap to make dynamic region monitoring easier. You can now use: regionBootstrap.disable() to stop scanning entirely, or regionBootstrap.removeRegion(region) to stop looking for a single region.
Related
Here is my simple implementation.
The MapFragment is already initialized. If I do the simulation mode the position indicator is showing but if I switched to the actual TBT navigation it is not showing where I am located.
PositionManager positioningManager;
if(positioningManager == null) {
positioningManager = PositioningManager.getInstance();
positioningManager.addListener(new WeakReference<>(positionChangedListener));
positioningManager.start(PositioningManager.LocationMethod.GPS_NETWORK);
}
positionIndicator = mMap.getPositionIndicator();
positionIndicator.setVisible(true);
positionIndicator.setAccuracyIndicatorVisible(true);
private PositioningManager.OnPositionChangedListener positionChangedListener =
new PositioningManager.OnPositionChangedListener() {
#Override
public void onPositionUpdated(PositioningManager.LocationMethod locationMethod,
GeoPosition geoPosition, boolean b) {
Log.d(TAG, "onPositionUpdated " + locationMethod.name());
Log.d(TAG, "Coordinates " +geoPosition.getCoordinate());
}
#Override
public void onPositionFixChanged(PositioningManager.LocationMethod locationMethod,
PositioningManager.LocationStatus locationStatus) {
Log.d(TAG, "onPositionFixChanged " + locationMethod.name() + " status " + locationStatus.name());
}
};
I have a list view with a list of channels on them and when I press one of the channels, it starts to load a streaming URL to watch the channel. However, I can still navigate through the list and select another entry in the list which causes an Exception to occur. How can I disable controller input similar to how I can disable touch input once something has been pressed?
Here is the code for my onItemClickListener:
channel_list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
main_progressBar.setVisibility(View.VISIBLE);
//to disable touch input
//getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
final int channel = channelListAdapter.getItem(position);
final String switch_major = majorChannelNumberList.get(channel);
Log.d(TAG, "Switch Major :" + switch_major);
final String switch_minor = minorChannelNumberList.get(channel);
Log.d(TAG, "Switch Minor :" + switch_minor);
final String switch_name = channelNameList.get(channel);
Log.d(TAG, "Switch Name :" + switch_name);
final String tuner = tuneLink + "Major=" + switch_major + "&Minor=" + switch_minor + "&Resolution=" + "1280x720";
Log.d(TAG, "Tuner String :" + tuner);
new Thread(new Runnable() {
#Override
public void run() {
String playlive = "";
String tuneResponse = tuneConnection.get_response(tuner);
if(tuneResponse.contains("successful")){
long startTime = System.currentTimeMillis();
do {
String hlsStatusResponse = hlsConnection.get_response(HLSLink);
Log.d(TAG,"HLS Status Response :" + hlsStatusResponse);
Matcher matcher = Pattern.compile("<hls_link>(.+?)</hls_link>").matcher(hlsStatusResponse);
while(matcher.find()){
playlive = matcher.group(1);
}
playlink = "http://" + ip + "/" + playlive;
} while (Objects.equals(playlive, "none") && (System.currentTimeMillis()-startTime)<20000);
if(!playlink.contains("none")){
streamConnection.get_response(playlink);
} else {
//TODO: implement some sort of message here to show no channel, see tablet app
}
} else {
Toast.makeText(OfflineActivity.this, "Ch " + switch_major + "-" + switch_minor + " " + switch_name + " is not available now",
Toast.LENGTH_LONG).show();
}
}
}).start();
//start player activity
streamConnection.responseHandler = new Handler(){
#Override
public void handleMessage(Message message){
Toast.makeText(OfflineActivity.this, "Tune to Channel " + switch_major + "-" + switch_minor, Toast.LENGTH_LONG).show();
Intent intent = new Intent(OfflineActivity.this, OfflinePlaybackActivity.class);
intent.putExtra("stream",playlink);
intent.putExtra("channel_index", channel);
startActivity(intent);
main_progressBar.setVisibility(View.INVISIBLE);
}
};
}
});
I know I can use
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
to disable touch input, looking for something similar for Amazon Fire TV.
Decided to use channel_list_view.setClickable(false) to prevent user from clicking on it.
I am trying to make an android app for RFID card reader (i am not using NFC), for this i connect one high frquency RFID card reader through OTG cable and i am using EditText where card number is displaying. it is working fine, but problem is sometime it detects multiple time card number.
1- Any idea how can i resolve this (i cannot put size limit condition because card number length is not fixed)?
2- One more problem when i am using ultra high frequency card reader then card is showing different value, any idea how can i make an android app which supports both frequency card readers.
Rfid continue reading tag its not one time reading so from this repetition you have to manage to your side. Check its reading data or not if yes then ignore.Below the call Where implement Rfid methods and its reading data handle.
public class ReaderListener implements RfidEventListener {
private RfidReader reader;
private ReadInventory eventForm;
//private ItemTransfer eventFormitm;
private final ToneGenerator tg = new ToneGenerator(5, 100);
private boolean isEnabled;
private Map<String, Long> scannedItemsMap = new TreeMap<String, Long>();
public ReaderListener(ReadInventory frm, String make, String macid) throws ReaderConnectionException, LicenseExpiryException, IOException, GeneralSecurityException {
Log.d("Test1", " "+make.toString().trim()+" "+ macid.toString().trim());
reader = RfidFactory.getInstance().getRfidReader(make.toString().trim(), macid.toString().trim(),
PlatformConnector.AndroidConnector.getPlatformName());
Log.d("Test2", " "+reader+" ");
//reader.removeAllListeners();
reader.registerListener(this);
setEnabled(true);
this.eventForm = frm;
}
#Override
public void handleData(String tagid, int arg1, int arg2) {
synchronized (scannedItemsMap) {
if (!scannedItemsMap.containsKey(tagid)) {
System.out.println("got data............ :" + tagid);
scannedItemsMap.put(tagid, System.currentTimeMillis());
if (eventForm != null) {
eventForm.handleData(tagid);
//this.tg.startTone(25);
Log.d("tagid", " " + tagid + " ");
}
/*if (eventFormitm != null) {
eventFormitm.handleData(tagid);
}*/
} else if (scannedItemsMap.containsKey(tagid)) {
scannedItemsMap.put(tagid, System.currentTimeMillis());
}
}
}
#Override
public void handleError(String msg) {
if (eventForm != null) {
eventForm.handleError(msg);
}
}
#Override
public boolean isEnabled() {
return isEnabled;
}
#Override
public void setEnabled(boolean arg0) {
this.isEnabled = arg0;
}
public boolean startScan(int power,int speed) throws ReaderConnectionException {
if (reader != null && !reader.isScanning()) {
reader.setSession(RfidSession.ONE);
reader.setPower(power);
reader.setScanSpeed(speed);
reader.startScan();
}
return true;
}
public void stopScan() throws ReaderConnectionException {
if (reader.isScanning())
reader.stopScan();
}
public boolean isScanning() {
return reader.isScanning();
}
public boolean isConnected() {
return reader.isConnected();
}
public void removeAll() {
scannedItemsMap.clear();
}
public void remove(String tagid) {
scannedItemsMap.remove(tagid);
}
public int getBatteryLevel(){
try {
return reader.getBatteryLevel();
}catch (Exception e){
return 0;
}
}
#Override
public void handleReaderEvent(ReaderEvent arg0) {
// TODO Auto-generated method stub
}
}
Now Handle The data in activity ....
Show in below method.
public void handleData(final String tagid) {
// TODO Auto-generated method stub
try {
final String Code_samplecode = convertHexToString(tagid);
// Log.e("Name", "Itemcode" + Code_samplecode);
if (SampleCode.contains(Code_samplecode)&& !p_SampleCode.contains(Code_samplecode)) {
// Scann items count
tgf.startTone(25);
int ind_val = SampleCode.indexOf(Code_samplecode);
if (ind_val != -1) {
final String SampleNo1 = SampleNo.get(ind_val);
final String StyleNo1 = StyleNo.get(ind_val);
final String SampleCode1 = SampleCode.get(ind_val);
final String StyleCode1 = StyleCode.get(ind_val);
//final String CartStyleCode1 = CartStyleCode.get(ind_val);
// final String CartStyleNo1 = CartStyleNo.get(ind_val);
SampleNo.remove(ind_val);
StyleNo.remove(ind_val);
SampleCode.remove(ind_val);
StyleCode.remove(ind_val);
runOnUiThread(new Runnable() {
#Override
public void run() {
// p_Code.add(Code.get(ind_val));
p_SampleNo.add(SampleNo1);
p_StyleNo.add(StyleNo1);
p_SampleCode.add(SampleCode1);
p_StyleCode.add(StyleCode1);
//Code.remove(ind_val);
// adapter3.notifyDataSetChanged();
// adapter1.notifyDataSetChanged();
total_item.setAdapter(null);
adapter3 = new Adapter_for_Inventoryitem(ReadInventory.this,
StyleNo, SampleNo);
total_item.setAdapter(adapter3);
present_item.setAdapter(null);
adapter1 = new Adapter_for_Inventoryitem(ReadInventory.this,
p_StyleNo, p_SampleNo);
present_item.setAdapter(adapter1);
textvie.setText("Total " + p_SampleNo.size() + " Found Styles");
textvi.setText("Total " + SampleNo.size() + " Available Styles");
List<Inventory> c = db.get_all_data_INVENTARY_Query("SELECT * FROM Inventory_n WHERE SampleCode ='" + SampleCode1 + "'");
if (c.size() > 0) {
db.execute_query("INSERT INTO Inventory_p (Code, SampleNo,StyleNo,SampleCode,StyleCode,CartStyleNo,CartStyleCode) VALUES ('" + c.get(0).getCode() + "' , \"" +
c.get(0).getSampleNo() + "\" , \"" + c.get(0).getStyleNo() + "\" , '" +
c.get(0).getSampleCode() + "' , '" + c.get(0).getStyleCode() + "' , \"" +
c.get(0).getCartStyleNo() + "\" , '" + c.get(0).getCartStyleCode() + "')");
}
db.execute_query("DELETE FROM Inventory_n WHERE SampleCode ='" + SampleCode1 + "'");
}
});
}
} else {
if (!SampleCode.contains(Code_samplecode) && !p_SampleCode.contains(Code_samplecode)
&& !not_fount_items.contains(Code_samplecode)) {
tgn.startTone(20);
scanneditems_unkown = scanneditems_unkown + 1;
runOnUiThread(new Runnable() {
#Override
public void run() {
not_fount_items.add(Code_samplecode);
not_fount_items_txt.setText("Total " + not_fount_items.size() + " Unknown Styles");
}
});
}
}
runOnUiThread(new Runnable() {
#Override
public void run() {
scan_counts.setText("Total " + p_SampleNo.size() + " Scanned");
scan_counts_unknown.setText("Total " + scanneditems_unkown + " Unknown");
last_scanned_items.setText("Item : " + Code_samplecode);
}
});
} catch (Exception e) {
e.printStackTrace();
Message message = new Message();
message.what = READEREXCEPTION;
itemDetectedHandler.sendMessage(message);
}
}
You need to Override
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
//To get the characters (One By one)
event.getDisplayLabel();
}
And use Debounce (I'll recommend using RX Java) if the card numbers are of different length.
What debounce does is, it will wait for a particular amount of time after a keyevent happens, So you can concat the whole string and then use it.
I have developed my application using this tutorial:
http://code.tutsplus.com/tutorials/how-to-recognize-user-activity-with-activity-recognition--cms-25851
Even though I request updates every 3 seconds (or for a change, 5 seconds, 10 seconds etc); the timing of the generated values is highly inconsistent. At times it would generate 4 values in 10 minutes! Why is the API being so inconsistent? Also, I'm unable to disconnect the API, even after I call API.disconnect(), I still keep getting values in logcat, which heats up the phone and consumes battery excessively.
Here is the full project: https://github.com/AseedUsmani/MotionAnalyser2
Basic Code:
1) Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_analysing);
mApiClient = new GoogleApiClient.Builder(this)
.addApi(ActivityRecognition.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mStartButton = (Button) findViewById(R.id.startButton);
mFinishButton = (Button) findViewById(R.id.finishButton);
mStartButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//resetting counter
for (int j = 0; j < 8; j++) {
mCount[j] = 0;
}
mServiceCount = 0;
mApiClient.connect();
mStartButton.setVisibility(View.INVISIBLE);
mFinishButton.setVisibility(View.VISIBLE);
}
}
mFinishButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mApiClient.disconnect();
}
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Intent intent = new Intent(this, ActivityRecognizedService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mApiClient, 3000, pendingIntent);
}
#Override
public void onConnectionSuspended(int i) {
Toast.makeText(AnalysingActivity.this, "Connection to Google Services suspended!", Toast.LENGTH_LONG).show();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Toast.makeText(AnalysingActivity.this, "Connection to Google Services failed!", Toast.LENGTH_LONG).show();
}
}
2) Service:
public class ActivityRecognizedService extends IntentService {
AnalysingActivity mObject = new AnalysingActivity();
int confidence;
public ActivityRecognizedService() {
super("ActivityRecognizedService");
}
public ActivityRecognizedService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent intent) {
if (ActivityRecognitionResult.hasResult(intent)) {
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
handleDetectedActivities(result.getProbableActivities());
}
}
private void handleDetectedActivities(List<DetectedActivity> probableActivities) {
confidence = mObject.confidence;
mObject.mServiceCount++;
for (DetectedActivity activity : probableActivities) {
switch (activity.getType()) {
case DetectedActivity.IN_VEHICLE: {
if (activity.getConfidence() >= confidence) {
mObject.mCount[0]++;
}
mObject.mActivity[0] = "In Vehicle: " + Integer.toString(activity.getConfidence()) + " " + Integer.toString(mObject.mCount[0]);
Log.e("ActivityRecogition", "In Vehicle: " + activity.getConfidence() + " " + Integer.toString(mObject.mCount[0]));
break;
}
case DetectedActivity.ON_BICYCLE: {
if (activity.getConfidence() >= confidence) {
mObject.mCount[1]++;
}
mObject.mActivity[1] = "Cycling: " + Integer.toString(activity.getConfidence()) + " " + Integer.toString(mObject.mCount[1]);
Log.e("ActivityRecogition", "Cycling: " + activity.getConfidence() + " " + Integer.toString(mObject.mCount[1]));
break;
}
case DetectedActivity.ON_FOOT: {
if (activity.getConfidence() >= confidence) {
mObject.mCount[2]++;
}
mObject.mActivity[2] = "On Foot: " + Integer.toString(activity.getConfidence()) + " " + Integer.toString(mObject.mCount[2]);
Log.e("ActivityRecogition", "On foot: " + activity.getConfidence() + " " + Integer.toString(mObject.mCount[2]));
break;
}
case DetectedActivity.RUNNING: {
if (activity.getConfidence() >= confidence) {
mObject.mCount[3]++;
}
mObject.mActivity[3] = "Running: " + Integer.toString(activity.getConfidence()) + " " + Integer.toString(mObject.mCount[3]);
Log.e("ActivityRecogition", "Running: " + activity.getConfidence() + " " + Integer.toString(mObject.mCount[3]));
break;
}
case DetectedActivity.STILL: {
if (activity.getConfidence() >= confidence) {
mObject.mCount[4]++;
}
mObject.mActivity[4] = "Still: " + Integer.toString(activity.getConfidence()) + " " + Integer.toString(mObject.mCount[4]);
Log.e("ActivityRecogition", "Still: " + activity.getConfidence() + " " + Integer.toString(mObject.mCount[4]));
break;
}
case DetectedActivity.WALKING: {
if (activity.getConfidence() >= confidence) {
mObject.mCount[5]++;
}
mObject.mActivity[5] = "Walking: " + Integer.toString(activity.getConfidence()) + " " + Integer.toString(mObject.mCount[5]);
Log.e("ActivityRecogition", "Walking: " + activity.getConfidence() + " " + Integer.toString(mObject.mCount[5]));
break;
}
case DetectedActivity.TILTING: {
if (activity.getConfidence() >= confidence) {
mObject.mCount[6]++;
}
mObject.mActivity[6] = "Tilting: " + Integer.toString(activity.getConfidence()) + " " + Integer.toString(mObject.mCount[6]);
Log.e("ActivityRecogition", "Tilting: " + activity.getConfidence() + " " + Integer.toString(mObject.mCount[6]));
break;
}
case DetectedActivity.UNKNOWN: {
if (activity.getConfidence() >= confidence) {
mObject.mCount[7]++;
}
mObject.mActivity[7] = "Unknown: " + Integer.toString(activity.getConfidence()) + " " + Integer.toString(mObject.mCount[7]);
Log.e("ActivityRecogition", "Unknown: " + activity.getConfidence() + " " + Integer.toString(mObject.mCount[7]));
break;
}
}
}
}
}
Per the requestActivityUpdates() documentation:
Activities may be received more frequently than the detectionIntervalMillis parameter if another application has also requested activity updates at a faster rate. It may also receive updates faster when the activity detection service receives a signal that the current activity may change, such as if the device has been still for a long period of time and is then unplugged from a phone charger.
Activities may arrive several seconds after the requested detectionIntervalMillis if the activity detection service requires more samples to make a more accurate prediction.
And
Beginning in API 21, activities may be received less frequently than the detectionIntervalMillis parameter if the device is in power save mode and the screen is off.
Therefore you should not expect calls exactly every 3 seconds, but assume that each call you get is the start of a state change - if you haven't received any callback, it is because nothing has changed.
Also note that the correct call to stop receiving updates is removeActivityUpdates(), passing in the same PendingIntent as you passed into requestActivityUpdates().
This is method stopPing() in MainActivity to save data to realm.
If I want to use data in realm from another class, how can I coding.
private void stopPing() {
linkEdt.setEnabled(true);
pingBtn.setText("Start Ping");
isPing = false;
count = 0;
endTime = getTime();
/* Open the Realm for the UI thread. */
realm = Realm.getInstance(realmConfig);
/* All writes must be wrapped in a transaction to facilitate safe multi threading */
realm.beginTransaction();
Ping ping = realm.createObject(Ping.class);
/* Add ip */
ping.set_ip(ip);
/* Add start time */
ping.set_startTime(startTime);
/* Add end time. */
ping.set_endTime(endTime);
/* Add down amount */
ping.set_downAmount(downtime);
/* Add ping speed time. */
PingTime pingtime = realm.createObject(PingTime.class);
for(Double speedTime : speedList){
pingtime.time = speedTime;
ping.get_times().add(pingtime);
}
/* Add time. */
for(String time : timeList){
pingtime.pingTime = time;
ping.get_pingTime().add(pingtime);
}
realm.commitTransaction();
/* stop handler. */
this.mHandler.removeCallbacks(m_Runnable);
}
When I want to query in another class it has error with realm -->> io.realm.Realm.allObjects(java.lang.Class)' on a null object reference
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ping_list);
for (Ping pers : realm.allObjects(Ping.class)) {
String startT, endT;
if (pers.get_stratTime() == null) {
startT = "None";
} else {
startT = pers.get_stratTime();
}
if (pers.get_endTime() == null) {
endT = "None";
} else {
endT = pers.get_endTime();
}
status += "Start time: " + startT + "\n End time: " + endT + "\n";
status += "Ping total: " + pers.get_times().size() + "\n";
status += "Down amount: " + pers.get_downAmount() + " time.\n";
for (int i = 0; i < pers.get_times().size(); i++) {
double speed = pers.get_times().get(i).time;
String time = pers.get_pingTime().get(i).pingTime;
status += "time (" + (i + 1) + "): " + speed + " ms. at " + time + ".\n";
}
}
System.out.println(status);
}
How are you creating the realm instance in the 2nd class? If you didn't call realm = Realm.getInstance(...) the variable will be null, resulting in the NullPointerException you are seeing.