I am trying to show a progress indicator when doing network requests with volley. I am getting the error "Only the original thread that create a view hierarchy can touch its views". I cannot figure out how to get my hideProgressDialog() onto the same thread as showProgressDialog(). Here's my code...
showProgressDialog("Logging you in");
String url = ApplicationController.getInstance().getBaseURL() + "Customer/LoginCustomer";
JsonRequest<String> jr = new JsonRequest<String>(Method.POST, url, jo.toString(), this.createSuccessListener(),
this.createErrorListener()) {
#Override
protected Response<String> parseNetworkResponse(NetworkResponse nr) {
hideProgressDialog();
try {
String str = new String(nr.data, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
};
ApplicationController.getInstance().addToRequestQueue(jr);
}
/** Create Volley Listeners **/
private Response.ErrorListener createErrorListener() {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
hideProgressDialog();
}
};
}
private Response.Listener<String> createSuccessListener() {
return new Response.Listener<String>() {
#Override
public void onResponse(String response) {
hideProgressDialog();}
};
}
Solution
Thanks to tautvydas. I ended up putting these methods in my base class.
protected void showProgressDialog(String message) {
if(mHandler == null){
mHandler = new Handler();
}
if (mDialog == null || !mDialog.isShowing()) {
mDialog = new ProgressDialog(getActivity());
mDialog.setMessage(message);
mDialog.setCancelable(false);
mDialog.setIndeterminate(true);
mDialog.show();
}
}
protected void hideProgressDialog() {
if (mDialog != null) {
mHandler.post(new Runnable() {
#Override
// this will run on the main thread.
public void run() {
mDialog.hide();
}
});
}
}
Create a Handler and pass a Runnable to it to run on the main thread.
1) Declare Handler in the constructor on onCreate() method by Handler handler = new Handler(). 2) Then in your parseNetworkResponse() method call
handler.post(new Runnable() {
#Override
// this will run on the main thread.
public void run() {
hideProgressDialog();
}
});
Related
Im using OkHttpClient to connect to an API.
Request request = new Request.Builder()
.url(BPI_ENDPOINT)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Toast.makeText(Test.this, "Error during BPI loading : "
+ e.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Call call, Response response)
throws IOException {
final String body = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
parseBpiResponse(body);
}
});
}
});
The parseBpiResponse just displays the data in TextView but the data request from the site takes place only once and in order to get the data again I need to either reopoen the activity or implement a button or swipe-screen etc,
How to call an API request constantly so that the data keeps updating instead of doing it through users input??
you can use Timer class to do a network call periodically
final long period = 0;
new Timer().schedule(new TimerTask() {
#Override
public void run() {
// do your task here
}
}, 0, period);
use this code but you should be careful about your activity and views in this code it my lead to nasty exception and memory leaks better thing to do is using live data with Recursion function !
new Thread(new Runnable() {
#Override
public void run() {
//Checks the life cycle of the activity and if activity was destroyed break the while loop and exits
while (true && getLifecycle().getCurrentState() != Lifecycle.State.DESTROYED) {
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Toast.makeText(Test.this, "Error during BPI loading : "
+ e.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Call call, Response response)
throws IOException {
final String body = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
if (getLifecycle().getCurrentState() != Lifecycle.State.DESTROYED)
parseBpiResponse(body);
}
});
}
});
try {
//Waits for 1 sec
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
Just make a recursive call .for example :
public void callAPI()
{
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Toast.makeText(Test.this, "Error during BPI loading : "
+ e.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Call call, Response response)
throws IOException {
final String body = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
parseBpiResponse(body);
}
});
**//just use handler/timer or thread to post event after some interval**
new android.os.Handler().postDelayed(new Runnable() {
#Override
public void run() {
callAPI();
}
},2000);
}
});
}
Also i suggest using Rxjava+Retrofit with OkHttp and use interval function to make it easier .
I've got this code:
#Override
public void onClick(View v) {
progressDoalog = new ProgressDialog(Hack.this);
progressDoalog.setMax(100);
progressDoalog.setMessage("Its loading....");
progressDoalog.setTitle("ProgressDialog bar example");
progressDoalog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDoalog.show();
new Thread(new Runnable() {
#Override
public void run() {
try {
while (progressDoalog.getProgress() <= progressDoalog
.getMax()) {
Thread.sleep(200);
handle.sendMessage(handle.obtainMessage());
if (progressDoalog.getProgress() == progressDoalog
.getMax()) {
progressDoalog.dismiss();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
Handler handle = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
progressDoalog.incrementProgressBy(1);
}
};
});
}
}
Where can I add a code to open new activity when the ProgressDialog will be at 100%? Which and where exactly? Thanks for your help!
You can't start an Activity from a Dialog, but what you can do is start the Activity from the old one using a OnDismissListener.
Take a look at the documemtation :
https://developer.android.com/reference/android/content/DialogInterface.OnDismissListener.html
I haven't noticed but you can check the progress in your Handler, check if it's 100%, dismiss the dialog and start the new Activity, remember that you gotta do this on the UI thread
I've created an AsyncTask class to handle sending and receiving from my server. What I'm trying to do is fire an event or callback when the data is received so I can use said data to manipulate the UI.
AsyncTask class:
public class DataCollectClass extends AsyncTask<Object, Void, JSONObject> {
private JSONObject collected;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
//#Override -Commented out because it doesn't like the override
protected void onPostExecute() {
try {
Log.d("Net", this.collected.getString("message"));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
protected JSONObject doInBackground(Object... params) {
OkHttpClient client = new OkHttpClient();
// Get Parameters //
String requestURI = (String) params[0];
RequestBody formParameters = (RequestBody) params[1];
Request request = new Request.Builder().url(requestURI).post(formParameters).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
// DO something on FAIL
}
#Override
public void onResponse(Call call, Response response) throws IOException {
String jsonResponse = response.body().string();
Log.d("Net", jsonResponse);
try {
DataCollectClass.this.collected = new JSONObject(jsonResponse);
Log.d("Net", DataCollectClass.this.collected.getString("message"));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
return collected;
}
}
This is working, it prints an expected line of JSON into the log.
It's called from the Activity as:
new DataCollectClass().execute(requestURI, formVars);
I've looked all over, and I can't seem to find a definitive answer on how (and where) to add a callback. Preferably, the callback code itself should be with the DataCollectClass so all related code is reusable in the same place.
Is there a way to create a custom event firing (similar to Javascript libraries) that the program can listen for?
I've been pulling my hair out over this!
UPDATE:
Since AsyncTask is redundant, I've removed it and rewrote the code (in case someone else has this same issue):
public class DataCollectClass {
private JSONObject collected;
public interface OnDataCollectedCallback {
void onDataCollected(JSONObject data);
}
private OnDataCollectedCallback mCallback;
public DataCollectClass(OnDataCollectedCallback callback, String requestURI, RequestBody formParameters){
mCallback = callback;
this.collect(requestURI, formParameters);
}
public JSONObject collect(String requestURI, RequestBody formParameters) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(requestURI).post(formParameters).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
//TODO Add what happens when shit fucks up...
}
#Override
public void onResponse(Call call, Response response) throws IOException {
String jsonResponse = response.body().string();
Log.d("Net", jsonResponse);
try {
DataCollectClass.this.collected = new JSONObject(jsonResponse);
if(mCallback != null)
mCallback.onDataCollected(DataCollectClass.this.collected);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
return collected;
}
}
Called from Activity:
new DataCollectClass(new DataCollectClass.OnDataCollectedCallback() {
#Override
public void onDataCollected(JSONObject data) {
if(data != null) {
try {
// Do Something //
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, requestURI, formVars);
All working perfectly!
Thanks!
If you want to utilize a callback for an AsyncTask you can handle it via the following.
Do something like this (modifying your code to add what is below)
public class DataCollectClass extends AsyncTask<Object, Void, JSONObject> {
public interface OnDataCollectedCallback{
void onDataCollected(JSONObject data);
}
private OnDataCollectedCallback mCallback;
public DataCollectClass(OnDataCollectedCallback callback){
mCallback = callback;
}
// your code that is already there
...
#Override
public onPostExecute(JSONObject response){
if(mCallback != null)
mCallback.onDataCollected(response);
}
}
Then to make the magic happen
new DataCollectClass(new OnDataCollectedCallback() {
#Override
public void onDataCollected(JSONObject data) {
if(data != null)
// DO something with your data
}
}).execute(requestURI, formVars);
However, it is worth noting, most networking libraries, including OkHttp, handle background threads internally, and include callbacks to utilize with the requests.
This also implements a custom interface, so others may be able to see how you could use this for any AsyncTask.
There is a asynchronous get in OkHttp, so you don't need an AsyncTask, but as a learning exercise, you could define your callback as a parameter something like so.
new DataCollectClass(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
// DO something on FAIL
}
#Override
public void onResponse(Call call, Response response) throws IOException {
JSONObject collected = null;
String jsonResponse = response.body().string();
Log.d("Callback - Net", jsonResponse);
try {
collected = new JSONObject(jsonResponse);
Log.d("Callback - Net", collected.getString("message"));
} catch (JSONException e) {
e.printStackTrace();
}
}
}).execute(requestURI, formVars);
The AsyncTask
public class DataCollectClass extends AsyncTask<Object, Void, Call> {
private Callback mCallback;
private OkHttpClient client;
public DataCollectClass(Callback callback) {
this.mCallback = callback;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
this.client = new OkHttpClient();
}
#Override
protected void onPostExecute(Call response) {
if (response != null && this.mCallback != null) {
response.enqueue(this.mCallback);
}
}
#Override
protected Call doInBackground(Object... params) {
// Get Parameters //
String requestURI = (String) params[0];
RequestBody formParameters = (RequestBody) params[1];
Request request = new Request.Builder().url(requestURI).post(formParameters).build();
return client.newCall(request); // returns to onPostExecute
}
}
Call Webservice using asynctask is an old fashioned. You can use Volley or retrofit.
But you can use this process to call Webservice . Here is steps:
Create an Interface and implements it in your Activity/Fragment
public interface IAsynchronousTask {
public void showProgressBar();
public void hideProgressBar();
public Object doInBackground();
public void processDataAfterDownload(Object data);
}
Create Class DownloadableAsyncTask . This class is:
import android.os.AsyncTask;
import android.util.Log;
public class DownloadableAsyncTask extends AsyncTask<Void, Void, Object> {
IAsynchronousTask asynchronousTask;
public DownloadableAsyncTask(IAsynchronousTask activity) {
this.asynchronousTask = activity;
}
#Override
protected void onPreExecute() {
if (asynchronousTask != null)
asynchronousTask.showProgressBar();
}
#Override
protected Object doInBackground(Void... params) {
try {
if (asynchronousTask != null) {
return asynchronousTask.doInBackground();
}
} catch (Exception ex) {
Log.d("BSS", ex.getMessage()==null?"":ex.getMessage());
}
return null;
}
#Override
protected void onPostExecute(Object result) {
if (asynchronousTask != null) {
asynchronousTask.hideProgressBar();
asynchronousTask.processDataAfterDownload(result);
}
}
}
Now in your Activity you will find this methods.
DownloadableAsyncTask downloadAsyncTask;
ProgressDialog dialog;
private void loadInformation() {
if (downloadAsyncTask != null)
downloadAsyncTask.cancel(true);
downloadAsyncTask = new DownloadableAsyncTask(this);
downloadAsyncTask.execute();
}
#Override
public void showProgressBar() {
dialog = new ProgressDialog(this, ProgressDialog.THEME_HOLO_LIGHT);
dialog.setMessage(" Plaese wait...");
dialog.setCancelable(false);
dialog.show();
}
#Override
public void hideProgressBar() {
dialog.dismiss();
}
#Override
public Object doInBackground() {
// Call your Web service and return value
}
#Override
public void processDataAfterDownload(Object data) {
if (data != null) {
// data is here
}else{
//"Internal Server Error!!!"
}
}
Now just call loadInformation() method then you will get your response on processDataAfterDownload().
And how should i solve it ?
This is my button click method that i call it from inside onCreate:
public void addListenerOnButton()
{
btnClick = (Button) findViewById(R.id.checkipbutton);
btnClick.setOnClickListener(new OnClickListener()
{
byte[] response = null;
#Override
public void onClick(View arg0)
{
text = (TextView) findViewById(R.id.textView2);
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
for (int i = 0; i < ipaddresses.length; i++)
{
try
{
response = Get(ipaddresses[i]);
if (response == null)
{
text.setText("Connection Failed: " + generateRunnablePrinter(i));
}
}
catch (Exception e)
{
String err = e.toString();
}
if (response != null)
{
try
{
final String a = new String(response, "UTF-8");
text.post(new Runnable()
{
#Override
public void run()
{
text.setText(a);
}
});
iptouse = ipaddresses[i].substring(0, 26);
connectedtoipsuccess = true;
Logger.getLogger("MainActivity(inside thread)").info(a);
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
Logger.getLogger("MainActivity(inside thread)").info("encoding exception");
}
Logger.getLogger("MainActivity(inside thread)").info("test1");
break;
}
else
{
}
}
}
});
t.start();
}
});
}
At this place in the method inside the FOR loop the variable 'i' should be final:
text.setText("Connection Failed: " + generateRunnablePrinter(i));
But since 'i' is also the variable of the FOR loop i can't make it final.
So i added the method : generateRunnablePrinter
private Runnable generateRunnablePrinter(final int value)
{
return new Runnable() {
public void run()
{
text.setText("Connection Failed: " + ipaddresses[value]);
}
};
}
But now using this method I'm getting the exception:
ViewRootImpl$CalledFromWrongThreadException
You can't change the UI "text of the TextView" from another thread so you can try AsyncTask to do the work in the background in doInBackground() method then change the UI in the method onPostExecute().
Check out the AsyncTask:
http://developer.android.com/reference/android/os/AsyncTask.html
Since you're adjusting your UI, you'll need to run it from the UI thread. I'd recommend this function:
runOnUiThread(new Runnable() {
#Override
public void run() {
// Your code here...
}
});
If you're calling it from anywhere else but an Activity, you'll need to either pass down the activity or get the activity using getActivity() (i.e. from a fragment), and then call the function from the activity, i.e. getActivity().runOnUiThread() { ... }
I am trying to validate the Nymi band asynchronously . But when I try to do that, I get the following exception:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
I have all the toasts in the following method as you can see:
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TestBluetooth.this, "Failed to initialize NCL library!", Toast.LENGTH_LONG).show();
}
});
But Still I get the exception. The method works fine when run normally in the onCreate() method,but fails to run asynchronously .
Edit: Even after removing all the toasts, I still get the exception.
Here is my Thread class,where I am calling the validate() asynchronously :
public class NymiAsync extends AsyncTask<Integer,Integer,Integer> {
#Override
protected Integer doInBackground(Integer... integers) {
try{
TestBluetooth tb=new TestBluetooth();
tb.startValidatingNymi();
}catch (Exception e){
e.printStackTrace();
}
return 0;
}
}
Here is the main class where I have the validate methods:
public class TestBluetooth extends Activity implements OnClickListener,ProvisionController.ProvisionProcessListener,
ValidationController.ValidationProcessListener {
boolean isBluetoothEnabled = false;
static boolean nclInitialized = false;
static final String LOG_TAG = "AndroidExample";
SharedPreferences prefs;
Button checkBlue,proviNymi,validateNymi,disconnectNymi;
ProvisionController provisionController;
ValidationController valiationController;
boolean connectNymi = true;
int nymiHandle = Ncl.NYMI_HANDLE_ANY;
NclProvision provision;
//NclProvision provisionmid;
String temp_ID,temp_Key;
public String keyuse;
public String iduse;
public LinearLayout progressbar;
public ProgressBar pbHeaderProgress;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.testbluetooth);
// I tried this too final Handler timedThread= new Handler(Looper.getMainLooper());
final Handler timedThread=new Handler();
timedThread.postDelayed(new Runnable() {
#Override
public void run() {
NymiAsync task=new NymiAsync();
task.execute(1,1,1);
}
},10000);
}
public void startValidatingNymi(){
progressbar = (LinearLayout) findViewById(R.id.linlaHeaderProgress);
pbHeaderProgress=(ProgressBar) findViewById(R.id.pbHeaderProgress);
pbHeaderProgress.getIndeterminateDrawable().setColorFilter(Color.parseColor("#1109EE"), android.graphics.PorterDuff.Mode.SRC_ATOP);
// prefs = getSharedPreferences(Util.SharedPrefKey, Context.MODE_PRIVATE);
// prefs.edit().clear().commit();
prefs=getSharedPreferences(Util.SharedPrefKey,MODE_PRIVATE);
temp_ID = prefs.getString(Util.provID, null);
temp_Key = prefs.getString(Util.provKey, null);
if ((temp_ID!=null) || (temp_Key!=null)){
// SHOW THE SPINNER WHILE LOADING FEEDS
progressbar.setVisibility(View.VISIBLE);
//Toast.makeText(getBaseContext(), "Nymi band is already provisined" , Toast.LENGTH_SHORT ).show();
initializeNcl();
provision = new NclProvision();
load();
if (valiationController == null) {
valiationController = new ValidationController(TestBluetooth.this);
}
else {
valiationController.stop();
}
valiationController.startValidation(TestBluetooth.this, provision);
proviNymi = (Button) findViewById(R.id.provisionNymi);
proviNymi.setOnClickListener(this);
proviNymi.setEnabled(false);
validateNymi = (Button) findViewById(R.id.validateNymi);
validateNymi.setOnClickListener(this);
validateNymi.setEnabled(false);
disconnectNymi = (Button) findViewById(R.id.disconnectNymi);
disconnectNymi.setOnClickListener(this);
disconnectNymi.setEnabled(false);
}else {
// Toast.makeText(getBaseContext(), "provision key is null!" , Toast.LENGTH_SHORT ).show();
checkBlue = (Button) findViewById(R.id.testBLuetooth);
checkBlue.setOnClickListener(this);
proviNymi = (Button) findViewById(R.id.provisionNymi);
proviNymi.setOnClickListener(this);
validateNymi = (Button) findViewById(R.id.validateNymi);
validateNymi.setOnClickListener(this);
validateNymi.setEnabled(false);
disconnectNymi = (Button) findViewById(R.id.disconnectNymi);
disconnectNymi.setOnClickListener(this);
disconnectNymi.setEnabled(false);
}
}
public void load(){
iduse = prefs.getString(Util.provID,null);
Toast.makeText(getBaseContext(), iduse , Toast.LENGTH_SHORT ).show();
keyuse = prefs.getString(Util.provKey,null);
if ((iduse!=null)||(keyuse!=null)) {
provision.id = new NclProvisionId();
provision.id.v = Base64.decode(iduse, Base64.DEFAULT);
provision.key = new NclProvisionKey();
provision.key.v = Base64.decode(keyuse, Base64.DEFAULT);
final String temp= keyuse.toString();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(), "the temp provision key is " +temp , Toast.LENGTH_SHORT ).show();
}
});
}else {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(), "Provision key is null!" , Toast.LENGTH_SHORT ).show();
}
});
}
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v.getId() == checkBlue.getId()){
// Toast.makeText(getBaseContext(), "Checking bluetooth is enabled or not!" , Toast.LENGTH_SHORT ).show();
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
} else {
if (!mBluetoothAdapter.isEnabled()) {
// Bluetooth is not enable :)
// Toast.makeText(getBaseContext(), " bluetooth is not enabled !" , Toast.LENGTH_SHORT ).show();
isBluetoothEnabled=false;
}else {
// Toast.makeText(getBaseContext(), " bluetooth is enabled !" , Toast.LENGTH_SHORT ).show();
isBluetoothEnabled=true;
Log.d("is nabled", "blue is enalble");
}
}
}
if (v.getId()==proviNymi.getId()){
connectNymi = true;
initializeNcl();
nymiHandle = -1;
if (provisionController == null) {
provisionController = new ProvisionController(TestBluetooth.this);
}
else {
provisionController.stop();
}
provisionController.startProvision(TestBluetooth.this);
}
if (v.getId()==validateNymi.getId()){
proviNymi.setEnabled(false);
if (valiationController == null) {
valiationController = new ValidationController(TestBluetooth.this);
}
else {
valiationController.stop();
}
valiationController.startValidation(TestBluetooth.this, provisionController.getProvision());
}
if (v.getId()==disconnectNymi.getId()){
prefs = getSharedPreferences(Util.SharedPrefKey, Context.MODE_PRIVATE);
prefs.edit().clear().commit();
if (nymiHandle >= 0) {
disconnectNymi.setEnabled(false);
validateNymi.setEnabled(true);
proviNymi.setEnabled(true);
Ncl.disconnect(nymiHandle);
nymiHandle = -1;
}
}
}
/**
* Initialize the NCL library
*/
protected void initializeNcl() {
if (!nclInitialized) {
if (connectNymi) {
initializeNclForNymiBand();
}
}
}
/**
* Initialize NCL library for connecting to a Nymi Band
* #return true if the library is initialized
*/
protected boolean initializeNclForNymiBand() {
if (!nclInitialized) {
NclCallback nclCallback = new MyNclCallback();
boolean result = Ncl.init(nclCallback, null, "NCLExample", NclMode.NCL_MODE_DEFAULT, this);
if (!result) { // failed to initialize NCL
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TestBluetooth.this, "Failed to initialize NCL library!", Toast.LENGTH_LONG).show();
}
});
return false;
}
nclInitialized = true;
// nclInitialized();
}
return true;
}
#Override
public void onStartProcess(ProvisionController controller) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TestBluetooth.this, "Nymi start provision ..",
Toast.LENGTH_LONG).show();
}
});
}
public void save(){
final String id = Base64.encodeToString(provision.id.v, Base64.DEFAULT);
final String key = Base64.encodeToString(provision.key.v, Base64.DEFAULT);
SharedPreferences pref = getSharedPreferences(Util.SharedPrefKey, MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString(Util.provID, id);
editor.putString(Util.provKey, key);
editor.apply();
editor.commit();
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(TestBluetooth.this, id + key,
Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onAgreement(final ProvisionController controller) {
nymiHandle = controller.getNymiHandle();
controller.accept();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TestBluetooth.this, "Agree on pattern: " + Arrays.toString(controller.getLedPatterns()),
Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onProvisioned(final ProvisionController controller) {
nymiHandle = controller.getNymiHandle();
provision = controller.getProvision();
controller.stop();
runOnUiThread(new Runnable() {
#Override
public void run() {
proviNymi.setEnabled(false);
validateNymi.setEnabled(true);
Toast.makeText(TestBluetooth.this, "Nymi provisioned: " + Arrays.toString(provision.id.v),
Toast.LENGTH_LONG).show();
save();
}
});
}
#Override
public void onFailure(ProvisionController controller) {
controller.stop();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TestBluetooth.this, "Nymi provision failed!",
Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onDisconnected(ProvisionController controller) {
controller.stop();
runOnUiThread(new Runnable() {
#Override
public void run() {
validateNymi.setEnabled(provision != null);
disconnectNymi.setEnabled(false);
Toast.makeText(TestBluetooth.this, "Nymi disconnected: " + provision,
Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onStartProcess(ValidationController controller) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TestBluetooth.this, "Nymi start validation for: " + Arrays.toString(provision.id.v),
Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onFound(ValidationController controller) {
nymiHandle = controller.getNymiHandle();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TestBluetooth.this, "Nymi validation found Nymi on: " + Arrays.toString(provision.id.v),
Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onValidated(ValidationController controller) {
nymiHandle = controller.getNymiHandle();
runOnUiThread(new Runnable() {
#Override
public void run() {
validateNymi.setEnabled(false);
disconnectNymi.setEnabled(true);
// HIDE THE SPINNER AFTER LOADING FEEDS
progressbar.setVisibility(View.GONE);
Toast.makeText(TestBluetooth.this, "Nymi validated!",
Toast.LENGTH_LONG).show();
prefs.edit().putBoolean(Util.isValidated, true).commit();
//move to new activity once nymi is validated
Intent intent = new Intent(TestBluetooth.this,CustomNotificationTest.class);
startActivity(intent);
}
});
}
#Override
public void onFailure(ValidationController controller) {
controller.stop();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TestBluetooth.this, "Nymi validated failed!",
Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onDisconnected(ValidationController controller) {
controller.stop();
runOnUiThread(new Runnable() {
#Override
public void run() {
disconnectNymi.setEnabled(false);
validateNymi.setEnabled(true);
proviNymi.setEnabled(true);
Toast.makeText(TestBluetooth.this, "Nymi disconnected: " + provision,
Toast.LENGTH_LONG).show();
}
});
}
/**
* Callback for NclEventInit
*
*/
class MyNclCallback implements NclCallback {
#Override
public void call(NclEvent event, Object userData) {
Log.d(LOG_TAG, this.toString() + ": " + event.getClass().getName());
if (event instanceof NclEventInit) {
if (!((NclEventInit) event).success) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(TestBluetooth.this, "Failed to initialize NCL library!", Toast.LENGTH_LONG).show();
}
});
}
}
}
}
}
Edit: After I made the NYmiAssync as inner class, I am able to run the it async using the following :
new Thread() {
public void run() {
TestBluetooth.this.runOnUiThread(new Runnable(){
#Override
public void run() {
try {
NymiAsync task = new NymiAsync();
task.execute(1, 1, 1);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}.start();
But, I have no idea, how to make it run for every 10 seconds.
The problem is in the asynctask:
public class NymiAsync extends AsyncTask<Integer,Integer,Integer> {
#Override
protected Integer doInBackground(Integer... integers) {
try{
TestBluetooth tb=new TestBluetooth();
tb.startValidatingNymi();
}catch (Exception e){
e.printStackTrace();
}
return 0;
}
}
Just make the class an inner class of TestBluetooth and then just call startValidatingNymi()
public class NymiAsync extends AsyncTask<Integer,Integer,Integer> {
#Override
protected Integer doInBackground(Integer... integers) {
try{
startValidatingNymi();
}catch (Exception e){
e.printStackTrace();
}
return 0;
}
}
that is because the code below in TestBlutooth:
final Handler timedThread=new Handler();
but in doInBackground you create a instance of TestBluetooth, so you get the exception