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.
Related
I'm transfering an image of 1 mb using the following code.
The image gets transferred successfully if a thread delay is implemented between each packets.
If the thread delay is not set all the packets are sent from BluetoothGattServer but the BluetoothGattCallback does not receive all the packets.
Can anyone guide in sending the packets without the thread delay
Implement thread between each packets
private void sendingContinuePacket(BluetoothGattCharacteristic characteristic,
byte[] CHARACTERS) {
boolean isComplete = false;
runOnUiThread(() -> {
tv_status.setText("Sending Data...!!");
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
});
// Check the data length is large how many times with Default Data (BLE)
int times = CHARACTERS.length / DEFAULT_BYTES_IN_CONTINUE_PACKET;
totalPackets = times;
Log.i("", "CHARACTERS.length() " + CHARACTERS.length);
byte[] packetNoByte;
byte[] sending_continue_hex = new byte[DEFAULT_BYTES_IN_CONTINUE_PACKET];
for (int time = 0; time <= times; time++) {
final int remainingTime = time;
if (!hasDisconnected) {
this.runOnUiThread(new Runnable() {
#Override
public void run() {
mRelativeLayout.setVisibility(View.VISIBLE);
if (totalPackets != 0) {
showProgress(totalPackets, remainingTime);
}
}
});
} else {
runOnUiThread(() -> {
mProgressBar.setProgress(0);
tv_progress.setText(0 + "%");
tv_timer.setText("00:00:00");
tv_imageSize.setText("");
tv_status.setText("");
Toast.makeText(PeripheralRoleActivity.this, "Something went wrong, Please Try again", Toast.LENGTH_SHORT).show();
customHandler.removeCallbacks(updateTimerThread);
});
return;
}
int a;
int b;
/**
* #param THREAD_SLEEP_TIME_FOR_NOTIFICATION
* this delay is placed to give a small pause while sending the data packe
* */
try {
Thread.sleep(Constants.THREAD_SLEEP_TIME_FOR_NOTIFICATION);
} catch (InterruptedException e) {
e.printStackTrace();
}
sentPacket = sentPacket + 1;
byte[] packetArray = Utils.getUtilsClass().toByteArray(sentPacket);
packetNoByte = Arrays.copyOf(packetArray, packetArray.length);
if (time == times) {
Log.i("", "LAST PACKET ");
int character_length = CHARACTERS.length
- DEFAULT_BYTES_IN_CONTINUE_PACKET * times;
byte[] sending_last_hex = new byte[character_length];
a = (sending_continue_hex.length) * time;
b = a + character_length;
if(b-a ==0){
return;
}
sending_last_hex = Arrays.copyOfRange(CHARACTERS, a, b);
byte[] last_packet =
new byte[packetNoByte.length + character_length];
System.arraycopy(packetNoByte, 0, last_packet,
0, packetNoByte.length);
System.arraycopy(sending_last_hex, 0, last_packet,
packetNoByte.length, sending_last_hex.length);
Log.d("Sending packets", Arrays.toString(last_packet));
// Set value for characteristic
characteristic.setValue(last_packet);
notifyCharacteristicChanged();
isComplete = true;
customHandler.removeCallbacks(updateTimerThread);
currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());
Log.d("Collection", "End Time: " + currentDateTimeString);
Utils.getUtilsClass().sendNotification(getApplicationContext(), "Data Transfer", "Transfer Complete");
} else {
Log.i("", "CONTINUE PACKET ");
a = ((sending_continue_hex.length) * time);
b = a + DEFAULT_BYTES_IN_CONTINUE_PACKET;
sending_continue_hex = Arrays.copyOfRange(CHARACTERS, a, b);
byte[] sending_continue_packet =
new byte[packetNoByte.length + sending_continue_hex.length];
System.arraycopy(packetNoByte, 0, sending_continue_packet,
0, packetNoByte.length);
System.arraycopy(sending_continue_hex, 0, sending_continue_packet,
packetNoByte.length, sending_continue_hex.length);
Log.d("data transfer a", String.valueOf(a));
Log.d("data transfer b", String.valueOf(b));
Log.d("data trans bytes", String.valueOf(sending_continue_hex.length));
if(output == null){
output = new ByteArrayOutputStream();
}
try {
if {
characteristic.setValue(sending_continue_packet);
Log.d("Sending packets", Arrays.toString(sending_continue_packet));
notifyCharacteristicChanged();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Log.d("Data byte", "times " + time);
if (isComplete) {
characteristic.setValue("Completed");
notifyCharacteristicChanged();
}
runOnUiThread(() -> tv_status.setText("Data sent!!"));
}
}
Updated Code
//the following function is used break the image byte [] into packets and store it in an arraylist
private void breakPackets(byte[] CHARACTERS) {
// Check the data length is large how many times with Default Data (BLE)
int times = CHARACTERS.length / DEFAULT_BYTES_IN_CONTINUE_PACKET;
totalPackets = times;
packetList = new ArrayList<>();
sendingPacket = 0;
Log.i("", "CHARACTERS.length() " + CHARACTERS.length);
byte[] sending_continue_hex = new byte[DEFAULT_BYTES_IN_CONTINUE_PACKET];
for (int time = 0; time <= times; time++) {
int a;
int b;
if (time == times) {
Log.i("", "LAST PACKET ");
int character_length = CHARACTERS.length
- DEFAULT_BYTES_IN_CONTINUE_PACKET * times;
byte[] sending_last_hex = new byte[character_length];
a = (sending_continue_hex.length) * time;
b = a + character_length;
sending_last_hex = Arrays.copyOfRange(CHARACTERS, a, b);
//packetList is an ArrayList<byte[]>
packetList.add(sending_last_hex);
startSendingPackets(sendingPacket);
} else {
a = (sending_continue_hex.length) * time;
b = a + DEFAULT_BYTES_IN_CONTINUE_PACKET;
sending_continue_hex = Arrays.copyOfRange(CHARACTERS, a, b);
packetList.add(sending_continue_hex);
}
Log.d("Data byte", "times " + time);
}
}
//the following function is used to set the byte[] from the arraylist to the characteristics and then notify the characteristics
private void startSendingPackets(int packet) {
isCommand = false;
mSampleCharacteristic.setValue(packetList.get(packet));
notifyCharacteristicChanged();
Log.i("packeting", "Sending ------------> " + packet);
}
/*************************************************/
#Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
//check if status is success
if (status == BluetoothGatt.GATT_SUCCESS) {
//if status is not successful isExecutable is false and the else loop is executed to resend the same packet that has failed
if (isExecutable) {
// Log.i("packeting", "Sent ------------> " + sendingPacket);
sendingPacket = sendingPacket + 1;
int size = packetList.size();
if (sendingPacket <= size-1) {
startSendingPackets(sendingPacket);
Log.d(MainActivity.TAG, "Notification sent. Status: " + status + " sending packet no --" + sendingPacket);
} else {
sendCommand("Completed");
}
} else {
startSendingPackets(sendingPacket);
isExecutable = true;
Log.d(MainActivity.TAG, "Notification sent. Status: " + status + " sending packet no --" + sendingPacket);
}
}else{
//if status is not successful
isExecutable = false;
Log.d(MainActivity.TAG, "Notification sent. fail Status: " + status );
}
}
As can be read in the documentation at https://developer.android.com/reference/android/bluetooth/BluetoothGattServerCallback.html#onNotificationSent(android.bluetooth.BluetoothDevice,%20int):
When multiple notifications are to be sent, an application must wait
for this callback to be received before sending additional
notifications.
This means after you have called notifyCharacteristicChanged, you cannot call notifyCharacteristicChanged again until the callback onNotificationSent has been received. So you need to remove your for-loop and refactor your code to follow the API rules.
The reason for this is to get flow control. If you just push new packets faster than the BLE link's throughput, the internal buffers get full and packet loss will occur. That's why a delay might seem to work, but it's not a robust solution so that's why you should wait for the onNotificationSent callback since that means the BLE stack is ready to accept new packets.
private void initFlightController() {
DJIAircraft aircraft = DJISimulatorApplication.getAircraftInstance();
if (aircraft == null || !aircraft.isConnected()) {
log("initFlightController: aircraft not connected");
showToast("Disconnected");
mFlightController = null;
return;
} else {
log("initFlightController: aircraft CONNECTED");
mFlightController = aircraft.getFlightController();
DJISimulator djiSimulator = mFlightController.getSimulator();
log("initFlightController: djiSimulator has started : "+djiSimulator.hasSimulatorStarted());
djiSimulator.setUpdatedSimulatorStateDataCallback(new DJISimulator.UpdatedSimulatorStateDataCallback() {
#Override
public void onSimulatorDataUpdated(final DJISimulatorStateData djiSimulatorStateData) {
log("onSimulatorDataUpdated: ");
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
String yaw = String.format("%.2f", djiSimulatorStateData.getYaw());
String pitch = String.format("%.2f", djiSimulatorStateData.getPitch());
String roll = String.format("%.2f", djiSimulatorStateData.getRoll());
String positionX = String.format("%.2f", djiSimulatorStateData.getPositionX());
String positionY = String.format("%.2f", djiSimulatorStateData.getPositionY());
String positionZ = String.format("%.2f", djiSimulatorStateData.getPositionZ());
mTextView.setText("Yaw : " + yaw + ", Pitch : " + pitch + ", Roll : " + roll + "\n" + ", PosX : " + positionX +
", PosY : " + positionY +
", PosZ : " + positionZ);
}
});
}
});
}
}
I am testing the sample code given for android in Dji-Developer. Every thing goes fine but the onSimulatorDataUpdated() doesnt get called.
it even prints the log
"initFlightController: djiSimulator has started : true"
I found the solution for the problem. The code doesn't have any problem, the RC has a button at the left front area which has to be set to P mode.
I am writing an Android program that parses data from the Translink API web page. The program works, but I am having an issue with the data that I am storing. It seems that each time the program loops, a "\n" is added to the String itself. Here is the code itself:
private class DownloadWebpageText extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String...urls) {
// params comes from the execute() call: params[0] is the url.
try {
// Test Code
for(int h=0; h<prev_stops.size(); h++) {
Document doc = Jsoup.connect("http://api.translink.ca/rttiapi/v1/stops/" + prev_stops.get(h) + "/estimates?&timeframe=120&apikey=XMy98rbwFPLcWWmNcKHc").get();
nextbuses = doc.select("nextbus");
schedules = doc.select("schedules");
String bus_times = "";
temp += "Arrival Times for Stop " + prev_stops.get(h) /*+ " (Previous Stop: " + prev_stop + "): \n" + "\nPrevious Stops: " + prev_stop*/;
for(int i=0; i<nextbuses.size(); i++) {
temp += parseData(nextbuses.get(i).select("routeno").toString()) + ": ";
schedule = schedules.get(i).children();
expectedleavetime = schedule.select("expectedleavetime");
for(int j=0; j<expectedleavetime.size(); j++) {
if(j != 0) {
temp = temp.concat(", ");
}
temp = temp.concat(parseData(expectedleavetime.get(j).toString()));
}
temp += "\n";
}
temp += "\n";
}
return "";
} catch (IOException e) {
return "Unable to retrieve web page. URL may be invalid.";
}
}
Where the parseData() function is just this:
public String parseData(String input) {
int beg = input.indexOf(">") + 1;
int end = input.lastIndexOf("<") - 1;
return input.substring(beg, end);
}
Here is the output from the console:
Arrival Times for Stop 56549
402:
4:10pm,
4:40pm,
5:10pm,
5:40pm
What I want the output to be like is this:
Arrival Times for Stop 56549
402: 3:40pm, 4:10pm, 4:40pm, 5:10pm
403: .....
You could use an ArrayList, which you define outside all for-loops
// Define our ArrayList
ArrayList<String> allStops = new ArrayList<String>();
// Define a string that holds information about the current stop
String currentStopInfo = "Arrival Times for Stop " + prev_stops.get(h);
for(int i=0; i<nextbuses.size(); i++) {
// Define a temporary String that holds all the times for a specific bus
String temp_2 = parseData(nextbuses.get(i).select("routeno").toString()) + ": ";
schedule = schedules.get(i).children();
expectedleavetime = schedule.select("expectedleavetime");
for(int j=0; j<expectedleavetime.size(); j++) {
if(j != 0) {
temp_2 += ", ";
}
temp_2 = temp_2.concat(parseData(expectedleavetime.get(j).toString()));
}
// Add the string that holds info for one bus to our Array
allStops.add(temp_2);
}
And when you want to print all of your strings(all of your stops for each bus)(every string contains information about one bus) you just do:
//Print the line that holds the current stop information
System.out.println(currentStopInfo);
for(String x : allStops) {
// Loop through our ArrayList, and print the information
System.out.println(x);
}
I have this problem, when I try to load new view, before I get service response I get black screen. Now to solve this issue I have used AsyncTask and I have solved the issue but the problem is I'm not getting Output from my service. Below is my code.
class GetInfo extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(NewHomeView.this);
pDialog.setMessage("Loading...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
/**
* Creating player
* */
protected String doInBackground(String... args) {
goal = MMBusinessFacade.baseURL;
goal = goal + "getGoal.jsp?acno=" + acnt;
goal = goal.replaceAll(" ", "%20");
res = MMBusinessFacade.getXML(goal, NewHomeView.this);
NewHomeView.res1 = gp.getOutput(res);
System.out.println("URL:" + goal);
System.out.println("Output:" + res1);
/********************************************************************************************/
spnrshi1 = MMBusinessFacade.baseURL;
spnrshi1 = spnrshi1 + "getFunds.jsp?acno=" + acnt;
spnrshi1 = spnrshi1.replaceAll(" ", "%20");
res = MMBusinessFacade.getXML(spnrshi1, NewHomeView.this);
System.out.println("URL" + spnrshi1);
list1 = fdp.getOutputOrg1(res);
list = fdp.getOutputOrg(res);
if (list1 != null && list1.size() > 0) {
for (int j = 0; j < list1.size(); j++) {
FundsAvailable prpobj = (FundsAvailable) list1.get(j);
FundDetail prpobj1 = (FundDetail) list.get(j);
ite = prpobj.getAmount() + " " + prpobj.getCurrency();
System.out.println("Item:" + ite);
NewHomeView.favail = prpobj1.getAmount() + " " + prpobj1.getCurrency();
NewHomeView.cur = prpobj.getCurrency();
}
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url)
{
// dismiss the dialog once done
pDialog.dismiss();
gl.setText(NewHomeView.res1);
avilfund.setText(NewHomeView.ite);
fndraised.setText(NewHomeView.favail);
}
}
Plz give your valuable advise.
Thanks
I think:
U should not use runOnUiThread in doInBackground function.Otherwise,doInBackground will return immediately。And you will get null with onPostExecute(null).So,failed.
right code:
protected String doInBackground(String... args) {
goal = MMBusinessFacade.baseURL;
goal = goal + "getGoal.jsp?acno=" + acnt;
goal = goal.replaceAll(" ", "%20");
res = MMBusinessFacade.getXML(goal, NewHomeView.this);
NewHomeView.res1 = gp.getOutput(res);
System.out.println("URL:" + goal);
System.out.println("Output:" + res1);
/********************************************************************************************/
spnrshi1 = MMBusinessFacade.baseURL;
spnrshi1 = spnrshi1 + "getFunds.jsp?acno=" + acnt;
spnrshi1 = spnrshi1.replaceAll(" ", "%20");
res = MMBusinessFacade.getXML(spnrshi1, NewHomeView.this);
System.out.println("URL" + spnrshi1);
list1 = fdp.getOutputOrg1(res);
list = fdp.getOutputOrg(res);
if (list1 != null && list1.size() > 0) {
for (int j = 0; j < list1.size(); j++) {
FundsAvailable prpobj = (FundsAvailable) list1.get(j);
FundDetail prpobj1 = (FundDetail) list.get(j);
ite = prpobj.getAmount() + " " + prpobj.getCurrency();
System.out.println("Item:" + ite);
NewHomeView.favail = prpobj1.getAmount() + " " + prpobj1.getCurrency();
NewHomeView.cur = prpobj.getCurrency();
}
}
}
}
You should not use runOnUiThread in your doInBackground, it make you loose interest in using AsyncTask. The best way to communicate with UI in doInBackground is to use the progress update process:
just implement in your asynTask:
#Override
protected void onProgressUpdate(MyProgressObject... mpo) {
super.onProgressUpdate(mpo);
//my UI update here
}
and when you need to update UI from within doInBackground just call publishProgress(MyProgressObject mpo)
I am working on an android application. In which i have slideShows. I am parsing these through an xml and after parsing them, saving in the SQLite DB. Majority of the slideshows are saved properly but, sometimes this happens that the slides are saved two times that is, every slide in the slideShow is saved two times obviously with different PK but same content. which should be avoided.
Partial code is here, where i am getting the slides and trying to store them in DB.
ArrayList<SlideShowItem> slideItems = null;
slideItems=Utils.database.getSlideItemOfUrl(Constants.StoriesTable,tempSlideShow.getFullStoryUrl().substring(0, index - 1), type);
if (slideItems == null) {
Log.d("store in DB: ", " when SlideItems == null ");
Log.d("SlideShow Title: ", tempSlideShow.getTitle());
Log.d("SlideShow pub Date: ", tempSlideShow.getPubDate());
slideItems = tempSlideShow.getSlideShow();
Utils.database.storeSlideItem(Constants.StoriesTable, myUrl,slideItems, type);
Utils.topStorySlidesArrayList = slideItems;
slideItems = null ;
} else {
Log.d("SlideShow Title: ", tempSlideShow.getTitle());
Utils.topStorySlidesArrayList = slideItems;
slideItems = null ;
}
and code of function storeSlideItem in DataBase is:
public synchronized void storeSlideItem(String tableName, String, url,ArrayList<SlideShowItem> list, String type) {
System.out.println("size of the Array list: " + list.size());
String newType = null;
if (type == null) {
newType = "List";
}else{
newType = type;
}
ArrayList<SlideShowItem> newList = new ArrayList<SlideShowItem>();
//newList = null;
Iterator<SlideShowItem> iterator = list.iterator();
while (iterator.hasNext())
{
SlideShowItem sSItem = iterator.next();
if(!newList.contains(sSItem))
{
newList.add(sSItem);
}
}
try {
for (int i = 0; i < newList.size(); i++) {
SlideShowItem item = newList.get(i);
String itemUrl = url + i;// Unique URL for the DB;
String imgString = null;
Log.e("Loop Counter", " time " + i);
Drawable drawable = item.getImage();
if (item.getBody() != null) {
item.setBody(item.getBody().replace('\'', '`'));
// replace as it create syntax error for storing data
}
if (item.getSubTitle() != null) {
item.setSubTitle(item.getSubTitle().replace('\'', '`'));
}
if (drawable != null) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
imgString = Base64.encodeBytes(b);
}
if (isOpen()) {
myDB.execSQL("INSERT INTO " + tableName + "(" + column[1] + "," + column[2] + "," + column[3] + "," + column[4] + "," + column[6]
+ "," + column[7] + ",type) VALUES('" + itemUrl + "','" + item.getSubTitle() + "','" + item.getBody() + "','"
+ item.getImagePath() + "','" + item.getIndex() + "','" + imgString + "','" + newType + "Slide')");
if (item.getBody() != null) {
item.setBody(item.getBody().replace('`', '\''));// " ' "
// replace as it create syntax error for storing data
}
if (item.getSubTitle() != null) {
item.setSubTitle(item.getSubTitle().replace('`', '\''));
}
if (tableName.equals(Constants.StoriesTable)) {
item.setItemId(getItemID(tableName, itemUrl));
Utils.hashListStoriesIds.put(itemUrl, item.getItemId());
if (imgString != null) {
Utils.hashListImages.put(item.getItemId(), new Boolean(true));
} else {
Utils.hashListImages.put(item.getItemId(), new Boolean(false));
}
}
}
}
} catch (Exception e) {
Log.e("Error", "Exception: storeSlideItem type " + e.toString());
} finally {
closeConnection();
}
}
Please tell me anything that can get me out of this irritating problem. Any help is appreciated.
in DB for duplication of slides the view is somewhat like:
1 abc USA 111
2 abc USA 111
and so on this was for one slide of a slideShow. if i have 3 slides in a slideshow, i'll get 6 entries in DB each slide being saved for two times.
Use HashSet instead of ArrayList