I want to have an algorithm for part of my android app code which will execute a particular code segment again and again if it doesnt meet the condition with different time intervals. in simple words retry the code multiple times after different time intervals.
For examaple,
I am uploading some string data, when there is an internet connectionI do a network connection check, and when there is no internet, it should check again automatically after 1 min. if positive, data is uploaded and if not, it should retry again after next 3 mins and for the third time also if positive, data is uploaded and if not, it should do the final check after next 5 mins and then if it cant get network then it should show toast no network.
How to do that with a simple algorithm?
Here the network connection scenario is just as an example. I want the algorithm for the 'retry' as i have explained there.
Thanks in advance.
Firstly, you have to declare a method to check if there's internet connection.
Using ConnectivityManager and NetworkInfo
public static boolean hasInternetConnection(final Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getActiveNetworkInfo();
if (ni == null) {
return false;
} else
return true;
}
Then...
try{
if(Util.hasInternetConnection(mcontext)){
//todo
#Override
public void onSuccess(String message) {
showAlertDialog("Alert",message);
}
#Override
public void onFail(String errorcode, String errormessage) {
showAlertDialog("Alert",errormessage);
}
});
}else{
showInternetRequiredDialog(getString(R.string.title_internet_require), getString(R.string.msg_no_internet_connection_setup));
return;
}
}catch (Exception ex){
ex.printStackTrace();
}
As for how you wanna write your checking logic, I'll leave it up to you
Using Handler, Timer can help.
Related
Good Afternoon, I am still very new to ESP32/android studio coding so I apologize for my beginner terminology. I am currently coding a project where I can control multiple stepper motors at the same exact time from the press of a button on my android application and the motors are connected to certain ESP32 GPIO pins, I am using the okhttp3 client as well. My code is below.
public class Connectivity {
public static String geturl (String url_esp32){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url_esp32)
.build();
try
{
Response response = client.newCall(request).execute();
return response.body().string();
} catch(IOException error) {
return error.toString();
}
}
}
above is my connectivity page for connecting to the requests for the esp32.
PBNow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// request information from esp32
// PB sandwich now, disable jelly motor
request_to_url("STEP");
request_to_url("DIR");
request_to_url("STEP2");
request_to_url("DIR2");
request_to_url("STEP4");
request_to_url("DIR4");
request_to_url("ledRED");
request_to_url("ledGREEN");
}
});
above is how im calling the requests for the esp32.
The problem I am having is that when these request_to_url lines are going line by line but I want them to all run at the exact same time. Is this possible.
Below are also my request_to_url function and request_data function.
public void request_to_url (String command) {
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.isConnected()) {
new request_data().execute("http://" + ip_address + "/" + command);
}else {
Toast.makeText(activity_2.this, "Not connected ", Toast.LENGTH_LONG).show();
}
}
private class request_data extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... url)
{
return Connectivity.geturl(url[0]);
}
#Override
protected void onPostExecute(String result_data) {
if(result_data != null)
{
}else{
Toast.makeText(activity_2.this, "Null data", Toast.LENGTH_LONG).show();
}
}
}
I apologize if the code is very sloppy, I am still very new. Thank you very much.
Besides the messy code in your app required to fire off multiple requests, the ESP32 has very limited network stack and resources, and cannot handle many simultaneous connections. If your app opens too many HTTP connections to the ESP32 at once, some will likely fail or have to wait for others to close.
Instead, you can do it all in a single request and tell the ESP32 to do multiple things at once. Pass the requests as parameters in the URL, like so:
http://ip-address/cmd?step=1&dir=0&ledGREEN=0&ledRED=1
Just have the handler on the ESP32 for the path /cmd look for the presence of each possible parameter and respond to it appropriately.
i need to use a code to check if i have internet access before i push files to the database ..
this is the code i am using. it works fine if i have internet connection but if not it freezes for like 6 or 7 seconds
public static boolean isInternetReachable() throws InterruptedException, IOException {
Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
int returnVal = p1.waitFor();
return (returnVal==0);
}
i want it to push files - file by file - to database and i want to check if the internet is working or not everytime
To check if a user is connected to the internet, use this.
public boolean hasInternetConnection() {
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
return manager.getActiveNetworkInfo() != null && manager.getActiveNetworkInfo().isConnected();
}
Your screen freezes because you're performing a long running task (uploading files) on the main thread which can lead to your app not being responsive. You'll have to move that operation off the main thread, either by using an AsyncTask, RxJava, or Coroutines (Kotlin).
See this
Handler hander = new Handler(this);
handler.postDelayed(new Runnable() {
#Override
public void run() {
//do what you want
},2000L);
I'm getting this exception in my logs: "clarifai2.exception.ClarifaiException: Maximum attempts reached of getting a default model." which is being generated by a large number of my android app users, but I am unable to replicate the exception or determine what is causing it. Any help on how to recreate or even better prevent this exception from occurring would be very helpful.
UPDATE:
I found the issue and am able to reproduce on demand, if no internet connection is available the Clarifai library throws this exception, there is no check for network connection state within the library. I can check for network connection in my app before building the clarifai client, but if the network connection is lost after the client is built this exception is generated, any ideas on how to prevent this? Thank you.
1 - Ensure data connection to internet is available on phone.
2 - Build clarifai client in onCreate
3 - Send clarifai predict request to food model
4 - Disable wifi and mobile data connections on phone
5 - Wait 10 to 15 seconds, can navigate to other activities, then clarifai throws "Clarifai Exception: Maximum attempts reached of getting a default model" and crashes the app.
Clarifai Library class which can throw this exception is available HERE
I call the buildClarifaiClient method below in my onCreate of the requesting activity.
private void buildClarifaiClient(){
if(clarifaiClient == null){
clarifaiClient = new ClarifaiBuilder("KeyString")
.client(new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
//.addInterceptor(new HttpLoggingInterceptor(logger::info).setLevel(HttpLoggingInterceptor.Level.BASIC))
.build()
)
.buildSync();
}
}
Request to Clarifai on ActivityResult after a picture is taken:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
if(clarifaiClient != null) {
snapSearchActivityResult = true;
taskClarifaiRequest = new AsyncTask<Void, Void, ClarifaiResponse<List<ClarifaiOutput<Concept>>>>() {
#Override
protected void onPreExecute() {
}
#Override
protected ClarifaiResponse<List<ClarifaiOutput<Concept>>> doInBackground(Void... params) {
// The default Clarifai model that identifies concepts in images
// Use this model to predict, with the image that the user just selected as the input
return clarifaiClient.getDefaultModels().foodModel().predict()
.withInputs(ClarifaiInput.forImage(ClarifaiImage.of(getPicByteData())))
.executeSync();
}
#Override
protected void onPostExecute(ClarifaiResponse<List<ClarifaiOutput<Concept>>> response) {
//setBusy(false);
if (!response.isSuccessful()) {
showErrorSnackbar(getString(R.string.clarifaiAPIContactError));
return;
}
final List<ClarifaiOutput<Concept>> predictions = response.get();
if (predictions.isEmpty()) {
showErrorSnackbar(getString(R.string.clarifaiAPIResultsError));
return;
}
List<Concept> concepts = predictions.get(0).data();
int conceptsSize = concepts.size();
Log.d("conceptsSize", String.valueOf(conceptsSize));
for (Concept c : concepts) {
// Do something with the value
Log.d("foodName", String.valueOf(c.name()));
Log.d("foodProb", String.valueOf(c.value()));
}
}
private void showErrorSnackbar(String errorString) {
Snackbar.make(
parentLayout,
errorString,
Snackbar.LENGTH_LONG
).show();
}
};
taskClarifaiRequest.execute();
} else {
Snackbar.make(
parentLayout,
"Unable to connect to Image API, try again.",
Snackbar.LENGTH_LONG
).show();
buildClarifaiClient();
}
}
Stacktrace:
Exception clarifai2.exception.ClarifaiException: Maximum attempts
reached of getting a default model.
clarifai2.dto.model.DefaultModels.update ()
clarifai2.dto.model.DefaultModels.access$000 ()
clarifai2.dto.model.DefaultModels$1.run ()
java.util.concurrent.ThreadPoolExecutor.runWorker
(ThreadPoolExecutor.java:1113)
java.util.concurrent.ThreadPoolExecutor$Worker.run
(ThreadPoolExecutor.java:588)
java.lang.Thread.run (Thread.java:818)
I'd say that the API key you use here doesn't have permissions for doing get model request. When you access the food model via getDefaultModels(), the model is first updated (via get model request) and only after that the predict request is run. If the first one fails, the second one doesn't run.
In the Java API client 2.3 which is about to be released next week, the call getDefaultModels() will no longer initiate get model request since most of the time you require only an ID of a default model, not the complete model data which get model request returns. Since only predict request will be performed, you will not need to have get model request permissions on your API key.
In the meanwhile, you can do one of two things. Either:
Add Models:Get permission to your API key. You do this by going to the API keys page, editing your API key, clicking ADVANCED under Scopes and checking Models:Get. You probably already have Predict permission checked.
Or use the model ID directly on the predict call. I've inserted the food default model ID (which you can also see in the DefaultModels.java link you posted above) into the predict call for you: client.predict("bd367be194cf45149e75f01d59f77ba7").withInputs(...).executeSync();.
I have a small functionality. Switching on the torch and keeping it on, till the user switches it off from my app or my app exits. Using :
params = camera.getParameters();
if (params.getFlashMode().equals(Parameters.FLASH_MODE_TORCH)) {
isFlashOn = true;
return;
}
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
And to switch off :
if (params.getFlashMode().equals(Parameters.FLASH_MODE_OFF)) {
isFlashOn = false;
return;
}
params.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
camera.stopPreview();
But I notice that this is not very robust. Works fine the first time, but after that (especially on my API levle 22 phone) might not work. I was thinking of testing with the android.hardware.camera2 as suggested here
Plan to use if (android.os.Build.VERSION.SDK_INT >20) and a strategy (a base interface implemented by two classes, one using old API and one the new camera2 API.
Is this safe on all devices? I saw that we can do it for android classes, but is it okay for our own classes too? Or are there devices which scan all our code and reject it if it has code that refers to API it does not know about?
I do not want to make two APKs as its a small functionality.
I make sure flash is available like this , not tested on all devices but in an emulator by Genymotion app did not crash.
public boolean torchInit() {
try {
PackageManager pm = app.getPackageManager();
// First check if device supports flashlight
boolean hasFlash = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
if (!hasFlash) {
Toast.makeText(app, "Flash not found or can\'t get hold of it. No torch", Toast.LENGTH_LONG).show();
return false;
}
camera = Camera.open();
Camera.Parameters params = camera.getParameters();
Log.i(LogId, "camera params flash: " + params.getFlashMode());
return true;
} catch (Throwable e) {
Log.e(LogId, "cameraFlashSetup " + e, e);
Toast.makeText(app, "Flash error, no torch. Description : " + e, Toast.LENGTH_LONG).show();
camera = null;
}
return false;
}
The flash interface to change between the two classes is :
public abstract class TorchInterface {
protected AppCompatActivity app;
public void init(AppCompatActivity ap){
app = ap;
}
public abstract boolean torchInit();
public boolean torchReInit(){
return torchInit();//if re init is not different than init
}
public abstract boolean torchOn();
public abstract boolean torchOff();
}
Update: new code worked but only if I:
mBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
Instead of:
mBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_MANUAL);
But then switches on flash as soon as init the app. I was going to chuck it, then realised on my Camera2Impl I can :
public boolean torchInit() {
//do nothing on usual init that app calls on create
return true;
}
And instead do the init on torch on (flash on):
public boolean torchOn() {
//if not in it, try first 3 times
if(mBuilder == null || mSession == null){
if(firstFewTimesTorchOn > 0){
firstFewTimesTorchOn--;
torchInit2();
try{
Thread.sleep(150);
}catch(Exception e){}
if(mBuilder == null || mSession == null) {
return false;
}
}
}
try {
mBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);//and etc
Android devices do not "scan" code - compiler does. Therefore, I don't see any issue with your idea. On contrary - using Strategy pattern is way better then if-else all over the code.
Something along these lines should work:
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
mFlashlightStrategy = new PostLollipopStrategy();
} else {
mFlashlightStrategy = new PreLollipopStrategy();
}
Is this safe on all devices?
Why dont't you put one check whether flash is available or not.
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
which will return true if a flash is available, false if not. You can write your further code in true block.
After reading a lot of topics on SOF & blog post, I have got the BroadcastReceiver working. But I have noticed sometime it does not work, specially when I am on call. I just want to know, does BroadcastReceiver work if I get SMS in-between the call ? or there is something is wrong in the code.
SmsReceiver.java
public class SmsReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Log.d("SmsReceiver Broadcast", "OK");
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
Log.d("Network is connected. Executing TheTask()", "OK");
new TheTask().execute("http://somedomain.tld/index.php?userId=12345678");
}
if (networkInfo == null) {
Log.d("Network is NOT connected.", "FAIL");
}
}
class TheTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... arg0) {
String text = null;
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(arg0[0]);
HttpResponse resp = httpclient.execute(httppost);
HttpEntity ent = resp.getEntity();
text = EntityUtils.toString(ent);
} catch (Exception e) {
e.printStackTrace();
}
return text;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
String tocheck = "Some text";
if(result.contains(tocheck))
{
Log.d("string contains some text", result);
}
}
}
}
AndroidManifest.xml
<receiver android:name=".SmsReceiver" android:enabled="true" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
I am using 3G network. It may be due to network disconnects. If so, is there any workaround to execute AsyncTask when my phone again get data network ?
EDIT:
Wrapped the AsyncTask into isConnected. Now if the phone is not connected to Internet & I get SMS the AsyncTask will not be executed. In that situation I want to use ScheduledExecutorService to schedule AsynckTask to be executed 4 times at the interval of 5 minutes within next 20 minutes. I will be highly obliged anyone can help me in this.
I cannot be sure about the disconnects since you haven't provided any stack trace. But I am pretty sure the SMS_RECEIVED broadcast action is being broadcasted system-wide when you receive sms. Now if you do not receive SMS due to bad connection or no connection at all it's perfectly logical for the system not to trigger an SMS_RECEIVED action since no SMS was received.
As for the
is there any workaround to execute AsyncTask when my phone again get
data network
you can implement another Broadcast Receiver that will listen for network changes but that doesn't seem such a good idea. You should try and reproduce the problem and check for any exceptions in your stack trace.
is something is wrong in the code.
Your receiver seems to be properly registered in your manifest,
the onReceive() method seems to be properly launching the AsyncTask,
the doInBackground doesn't seem to have any problem and onPostExecute (although the official example seems to omit any call to super) seems to be just fine.
Conclusion: Try to reproduce the problem and gather data from the stack trace as to what might cause the error (network overhead might be one the causes but that's just speculation).