I want to run my Async Task which fetches the co-odinates with a certain accuracy and fires up a different activity if it gets co-ordinates.
Now I want to setup a time so that if it doesn't gets the co-ordinates with a set accuracy then the Async task should destroy itself (remove location updates etc.) and the default value for Lattitude/Longitude is passed.
I tried using this:
new GetGPShotfix().execute().get(1, TimeUnit.MINUTES); so as to set a timeout for this async for a min and then proceed onto the next line/task below this async execute call.
But in my case it skips over to the next line without waiting for the timeout set by Async.
How can I make it execute the way I want? I also tried using thread's join() but apparently results were same :(
Update:
Here's my code (for gpshotfix() Async):
private class GetGPShotfix extends AsyncTask<Void, Void, Void> {
// ProgressDialog progressDialogGPS;
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.i("GPSfixer", "Ready to get GPS Hotfix");
}
#Override
protected Void doInBackground(Void... params) {
try {
LocationRetriever myLoc = new LocationRetriever();
// myLoc.getUserLoc();
//if (gotLoc == 0 && (firstLoc.getAccuracy() > 10)) {
if (gotLoc == 0) {
myLoc.getUserLoc();
}
} catch (Exception e) {
Log.i("GPSfixer", "GPS Hotfix Failed!", e);
}
finally {
Log.i("GPSfixer", "Get GPS Hotfix Completed...");
}
return null;
}
#Override
protected void onCancelled() {
Log.i("GPSfixer", "Get GPS Hotfix Cancelled");
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Log.i("GPSfixer", "GPS Hotfix cycle completed");
System.out.println("Lon :" + myCurrentLon + "Lon2: " + finalLonNow);
System.out.println("Lat :" + myCurrentLat + "Lat2: " + finalLatNow);
//pDialog2.dismiss();
// progressDialogGPS.dismiss();
}
}
public class LocationRetriever {
final LocationManager locationManager = (LocationManager) StoreSelection.this.getSystemService(Context.LOCATION_SERVICE);
final LocationListener locationListener = new LocationListener() {
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(),
provider + " is disabled!", Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(),
"Please standby..enabling " + provider,
Toast.LENGTH_SHORT).show();
// explicitly enable GPS
Intent enableGPS = new Intent("android.location.GPS_ENABLED_CHANGE");
enableGPS.putExtra("enabled", true);
sendBroadcast(enableGPS);
// explictly disable GPS
/*
* Intent intent = new
* Intent("android.location.GPS_ENABLED_CHANGE");
* intent.putExtra("enabled", false); sendBroadcast(intent);
*/
}
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(),
provider + " is enabled..", Toast.LENGTH_SHORT).show();
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
/*
* System.out.println("val of status: " + status + " provider: "
* + provider);
*/
if (status == 1) {
Toast.makeText(getApplicationContext(),
provider + " is enabled & available..",
Toast.LENGTH_SHORT).show();
System.out.println(provider + " is NOT available!");
} else {
System.out.println(provider + " is NOT available!");
}
/* progressDialogGPS.dismiss(); */
}
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
// ORIG CODE --BELOW--
// moved lat/lon vars to top ^
myCurrentLon = location.getLongitude();
myCurrentLat = location.getLatitude();
firstLoc = location;
myCurrentLon = Double.parseDouble(new DecimalFormat("##.#########")
.format(myCurrentLon));
myCurrentLat = Double.parseDouble(new DecimalFormat("##.#########")
.format(myCurrentLat));
/*Toast.makeText(getApplicationContext(),
myCurrentLat + " " + myCurrentLon, Toast.LENGTH_SHORT)
.show();*/
System.out.println(myCurrentLat + " " + myCurrentLon);
float acc=location.getAccuracy();
/*Toast.makeText(getApplicationContext(), "Acc.: " + acc,Toast.LENGTH_SHORT).show();*/
// --
// get best out of 2 locs. --BEGINS--
/*
* makeUseOfNewLocation(location);
*
* if(currentBestLocation == null){ currentBestLocation =
* location; }
*/
if (myCurrentLon != null && myCurrentLat != null && (firstLoc.getAccuracy() <= 10)) { // added
// chk
// for
// online..
gotLoc = 1;
System.out.println("OK GOTLOC == 1 !");
System.out.println("Got your Current Location..disabling GPS to save Battery Power..");
Toast.makeText(getApplicationContext(), "Got your Current Location..disabling GPS to save Battery Power..", Toast.LENGTH_SHORT).show();
// removing updates
// locationManager.removeUpdates(locationListener);
// explicitly turning off GPS
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", false);
sendBroadcast(intent);
System.out.println("GPS disabled!");
finalLatNow = myCurrentLat;
finalLonNow = myCurrentLon;
//
// if(gotLoc == 0){
if (myCurrentLon != null
&& myCurrentLat != null && (firstLoc.getAccuracy() <= 10)) {
// locationManager.removeUpdates(locationListener);
gotLoc = 1;
Intent i = new Intent(StoreSelection.this, LastVisitDetails.class);
i.putExtra("currUsrLon", myCurrentLon); // 2nd
i.putExtra("currUsrLat", myCurrentLat); // 1st
i.putExtra("storeID", selStoreID);
i.putExtra("selStoreName", selStoreName);
i.putExtra("imei", uuid);
i.putExtra("date", userDate);
runOnUiThread(new Runnable() {
public void run() {
try {
// stuff here
pDialog2.dismiss();
} catch (Exception e) {
e.printStackTrace();
}
}
});
System.out.println("--Removing Loc. Updates--");
remUpdates();
syncTIMESTAMP = System.currentTimeMillis();
Date dateobj = new Date(syncTIMESTAMP);
SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
fullFileName1 = df.format(dateobj);
dbengine.open();
dbengine.UpdateStoreStartVisit(selStoreID, fullFileName1);
dbengine.close();
startActivity(i);
finish();
} else {
if (myCurrentLon == null && myCurrentLat == null) {
// alert + GPS not locking on..do something()
} else {
}
/*if (!isOnline()) {
// alert + not online...do something()
showNoConnAlert();
} else {
}*/
}
//
/*
* } else{}
*/
} else {
System.out.println("INSIDE ELSE -- GOTLOC");
}
}
};
// locationManager.requestLocationUpdates(locationManager.getBestProvider(new
// Criteria(), true), 2000, 4, locationListener);
// enable gps everytime we request location update
/*
* Intent enableGPS = new Intent("android.location.GPS_ENABLED_CHANGE");
* enableGPS.putExtra("enabled", true); sendBroadcast(enableGPS);
*/
// ** ORIG Grequest location updates from GPS string
/*
* locationManager.requestLocationUpdates(locationManager.GPS_PROVIDER,
* ONE_MIN, 4, locationListener);
*/
// ** now remove updating of co-ordinates
// locationManager.removeUpdates(locationListener);
/*public Location getBestLoc(){
if(firstLoc.getAccuracy() <= newLoc.getAccuracy() && newLoc.getAccuracy() <= 10) {
return firstLoc;
}
else if(newLoc.getAccuracy() <= firstLoc.getAccuracy() && newLoc.getAccuracy() <= 10){
return newLoc;
}
else {
return newLoc;
}
}*/
void getUserLoc() {
if (gotLoc == 1 && (firstLoc.getAccuracy() <= 10)) {
locationManager.removeUpdates(locationListener);
} else {
}
final Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setHorizontalAccuracy(Criteria.ACCURACY_FINE);
// criteria.setVerticalAccuracy(Criteria.NO_REQUIREMENT);
criteria.setAltitudeRequired(false);
// criteria.setBearingAccuracy(Criteria.NO_REQUIREMENT);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
runOnUiThread(new Runnable() {
public void run() {
try {
// stuff here
/*
* progressDialogGPS = ProgressDialog.show(_activity,
* null, null);
* progressDialogGPS.setContentView(R.layout.loader);
* progressDialogGPS
* .getWindow().setType(WindowManager.LayoutParams
* .TYPE_KEYGUARD_DIALOG);
*/
/*locationManager
.requestLocationUpdates(locationManager
.getBestProvider(criteria, true),
TEN_SECS, 4, locationListener);*/
locationManager.requestLocationUpdates(locationManager.GPS_PROVIDER, 0l, 0.0f, locationListener);
// remove updates #
if (gotLoc == 1 && (firstLoc.getAccuracy() <= 10)) {
locationManager.removeUpdates(locationListener);
} else {
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
/*
* try { Thread.currentThread().sleep(2000); } catch
* (InterruptedException e) { // TODO Auto-generated catch block
* e.printStackTrace(); }
*/
}
void remUpdates() {
//if(firstLoc.getAccuracy() <= 10){
locationManager.removeUpdates(locationListener);
//}
//else {}
}
}
Any help is appreciable..
When using execute.get(1, TimeUnit.MINUTES) it converts async task to synchronus. Using async task is of no use in that case. You can start a separate thread when starting asynctask to keep a watch for time and do the required operation after that. You can create a class implmenting runnable and pass asyctask as constructor argument and cancel it inside.
class checkAyscTask implements Runnable {
AsyncTask<Void, Void, Boolean> mAT;
Context context;
public checkAyscTask(AsyncTask<Void, Void, Boolean> at) {
mAT = at;
}
#Override
public void run() {
mHandler.postDelayed(runnable, 60000);
// After 60sec the task in run() of runnable will be done
}
Handler mHandler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
if (mAT.getStatus() == Status.RUNNING || mAT.getStatus() == Status.PENDING) {
mAT.cancel(true); //Cancel Async task or do the operation you want after 1 minute
}
}
};
}
task_GetGPS = new GetGPShotfix();
task_GetGPS.execute();
checkAyscTask chk = new checkAyscTask(task_GetGPS);
// Thread keeping 1 minute time watch
(new Thread(chk)).start();
Related
Simple as that, I made a program with subscription, when the user subscribe, a boolean value turns to true.
when i test my software, if i cancel the subscription or it is automatically finished, the boolean value still return true.
I need to put in my code a check to see if the subscription is still available or not
As I am new to android studio, I have looked for that problem for 2 weeks so far but didn't find a solution for it.
All the solutions and posts are talking a bout the old in-App library (AIDL) with this magic line
Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
but it seems that doesn't work in the new Google Play Billing library.
here is my Billing Activity:
;
public class BillingActivity extends AppCompatActivity implements PurchasesUpdatedListener {
private static final String TAG = "BillingActivity";
private Button button;
protected SharedPreferences mSharedPreferences;
private boolean checkActivation;
private BillingClient mBillingClient;
private List<String> skuList;
private SkuDetailsParams.Builder skuParams;
private BillingFlowParams flowParams;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_billing);
// Shred Preferences & Active user Initialize
checkActivation = false;
mSharedPreferences = this.getSharedPreferences("com.aterosolutions.customerspremiums", Context.MODE_PRIVATE);
if (mSharedPreferences.getInt("activeUser", 0) == 1) { // 0 ==> InActiveUser 1 ==> ActiveUser
//mSharedPreferences.edit().putInt("activeUser", 1).apply();
checkActivation = true;
} else {
//mSharedPreferences.edit().putInt("activeUser", 0).apply();
checkActivation = false;
}
Toast.makeText(this, checkActivation + "", Toast.LENGTH_SHORT).show();
// SKU List
skuList = new ArrayList<>();
skuList.add("premiums_subscribe");
skuParams = SkuDetailsParams.newBuilder();
skuParams.setSkusList(skuList).setType(BillingClient.SkuType.SUBS);
// Establish connection to billing client
mBillingClient = BillingClient.newBuilder(this).enablePendingPurchases().setListener(this).build();
mBillingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(BillingResult billingResult) {
Log.i(TAG, "onBillingSetupFinished: start" + billingResult.getResponseCode());
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.i(TAG, "onBillingSetupFinished: second congrat");
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
Log.i(TAG, "onBillingSetupFinished: you own it");
} else {
Log.i(TAG, "onBillingSetupFinished: not your product");
}
}
#Override
public void onBillingServiceDisconnected() {
Toast.makeText(BillingActivity.this, "Connection Error", Toast.LENGTH_SHORT).show();
Log.i(TAG, "onBillingServiceDisconnected: Connection Error");
}
});
queryPurchases();
//checkPurchsedItem();
// Button Handle
button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mBillingClient.querySkuDetailsAsync(skuParams.build(), new SkuDetailsResponseListener() {
#Override
public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) {
flowParams = BillingFlowParams.newBuilder().setSkuDetails(skuDetailsList.get(0)).build();
BillingResult response = mBillingClient.launchBillingFlow(BillingActivity.this, flowParams);
Log.i(TAG, "onSkuDetailsResponse: " + billingResult.getResponseCode());
Log.i(TAG, "onSkuDetailsResponse: response OK");
Log.i(TAG, "onSkuDetailsResponse: my test" + response);
Log.i(TAG, "onSkuDetailsResponse: queryPurshase01 " + mBillingClient.queryPurchases(BillingClient.SkuType.SUBS));
/* (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
flowParams = BillingFlowParams.newBuilder().setSkuDetails(skuDetailsList.get(0)).build();
mBillingClient.launchBillingFlow(BillingActivity.this, flowParams);
Log.i(TAG, "onSkuDetailsResponse: response OK");
}else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED && skuDetailsList != null){
Log.i(TAG, "onSkuDetailsResponse: response already Owned");
}else {
Log.i(TAG, "onSkuDetailsResponse: response something else");
}*/
}
});
}
});
}
#Override
public void onPurchasesUpdated(BillingResult billingResult, #Nullable List<Purchase> purchases) {
Log.i(TAG, "onPurchasesUpdated: start /// purchses"+ billingResult.getResponseCode() );
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK /*&& purchases != null*/) {
mSharedPreferences.edit().putInt("activeUser", 1).apply();
MainScreenActivity.activeUser = true;
for (Purchase purchase : purchases) {
handleNewPurchase(purchase);
}
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED /*&& purchases != null*/) {
Log.i(TAG, "onPurchasesUpdated: You Already Own It");
Toast.makeText(this, "Already Owned", Toast.LENGTH_SHORT).show();
mSharedPreferences.edit().putInt("activeUser", 1).apply();
MainScreenActivity.activeUser = true;
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED /*&& purchases != null*/) {
Log.i(TAG, "onPurchasesUpdated: User Canceled");
Toast.makeText(this, "User Canceled", Toast.LENGTH_SHORT).show();
} else {
Log.i(TAG, "onPurchasesUpdated: other error " + billingResult.getResponseCode());
}
}
private void handleNewPurchase(Purchase purchase) {
Log.i(TAG, "handleNewPurchase: queryPurshase00 " + mBillingClient.queryPurchases(BillingClient.SkuType.SUBS).getBillingResult());
for (int i = 0; i < skuList.size(); i++) {
if (purchase.getSku() == skuList.get(i)) {
mSharedPreferences.edit().putInt("activeUser", 1).apply();
MainScreenActivity.activeUser = true;
Toast.makeText(this, "congrat dear", Toast.LENGTH_SHORT).show();
Log.i(TAG, "handleNewPurchase: product purchsed ");
// Acknowledge the purchase if it hasn't already been acknowledged.
if (!purchase.isAcknowledged()) {
Log.i(TAG, "handlePurchase: ok02");
AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = new AcknowledgePurchaseResponseListener() {
#Override
public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
}
};
Log.i(TAG, "handleNewPurchase: aknowledge done");
mBillingClient.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
} else {
Log.i(TAG, "handleNewPurchase: no need to aknowledge");
}
}
}
}
private void queryPurchases() {
Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.SUBS);
if (purchasesResult != null) {
List<Purchase> purchaseList = purchasesResult.getPurchasesList();
if (purchaseList == null) {
return;
}
if (!purchaseList.isEmpty()){
for (Purchase purchase : purchaseList){
if (purchase.getSku().equals(skuList.get(0))){
//mSharedPreferences.edit().putInt("activeUser", 1).apply();
//MainScreenActivity.activeUser = true;
}
}
}
}
}
#Override
protected void onDestroy() {
super.onDestroy();
mBillingClient.endConnection();
}
private void checkPurchsedItem(){
mBillingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.SUBS, new PurchaseHistoryResponseListener() {
#Override
public void onPurchaseHistoryResponse(BillingResult billingResult, List<PurchaseHistoryRecord> purchaseHistoryRecordList) {
Log.i(TAG, "onPurchaseHistoryResponse: " + billingResult.getResponseCode());
}
});
Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.SUBS);
Log.i(TAG, "checkPurchsedItem: " + purchasesResult.getBillingResult());
try {
Log.i(TAG, "checkPurchsedItem: " + purchasesResult.getPurchasesList().size());
}catch (Exception e){
e.printStackTrace();
}
Log.i(TAG, "checkPurchsedItem: " + purchasesResult.getResponseCode());
Log.i(TAG, "checkPurchsedItem: " + purchasesResult.getBillingResult());
}
}
After lots of headache (like always with Google APIs and services) I figured out how one can access Google Play Developer API information (like billing) by using existing APIs.
1.) Create in Developer API Console a service account (JSON) key:
2.) Download this service-account-private-key.json file (don't mistake it with the OAuth2.0 client secret file!).
3.) In Google Play Developer Console go to Settings -> Users & Permissions -> Invite New User and set as user e-mail of the new user the client_email from the downloaded file. Assign the access rights you want to give to this users via the checkboxes inside this view (for example 'View financial data').
4.) Add the proper dependency to your project (version ...-1.23.0 does not work for me):
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-androidpublisher</artifactId>
<version>v2-rev50-1.22.0</version>
</dependency>
5.) Load the service-account-private-key.json file into your application. In my case it's a webserver:
#Singleton
#Startup
public class WebserverConfiguration
{
private String serviceAccountPrivateKeyFilePath;
/** Global instance of the HTTP transport. */
public static HttpTransport HTTP_TRANSPORT;
/** Global instance of the JSON factory. */
public static JsonFactory JSON_FACTORY;
private GoogleCredential credential;
#PostConstruct
public void init()
{
assignServiceAccountFileProperty();
initGoogleCredentials();
}
public String getServiceAccountPrivateKeyFilePath()
{
return serviceAccountPrivateKeyFilePath;
}
public GoogleCredential getCredential()
{
return credential;
}
private void initGoogleCredentials()
{
try
{
newTrustedTransport();
newJsonFactory();
String serviceAccountContent = new String(Files.readAllBytes(Paths.get(getServiceAccountPrivateKeyFilePath())));
InputStream inputStream = new ByteArrayInputStream(serviceAccountContent.getBytes());
credential = GoogleCredential.fromStream(inputStream).createScoped(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER));
}
catch (IOException | GeneralSecurityException e)
{
throw new InitializationException(e);
}
}
private void newJsonFactory()
{
JSON_FACTORY = JacksonFactory.getDefaultInstance();
}
private void assignServiceAccountFileProperty()
{
serviceAccountPrivateKeyFilePath = System.getProperty("service.account.file.path");
if (serviceAccountPrivateKeyFilePath == null)
{
throw new IllegalArgumentException("service.account.file.path UNKNOWN - configure it as VM startup parameter in Wildfly");
}
}
private static void newTrustedTransport() throws GeneralSecurityException, IOException
{
if (HTTP_TRANSPORT == null)
{
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
}
}
}
6.) Now I am able the fetch Google Play Developer API information, e.g. reviews:
private void invokeGoogleApi() throws IOException
{
AndroidPublisher publisher = new AndroidPublisher.Builder(WebserverConfiguration.HTTP_TRANSPORT, WebserverConfiguration.JSON_FACTORY, configuration.getCredential()).setApplicationName("The name of my app on Google Play").build();
AndroidPublisher.Reviews reviews = publisher.reviews();
ReviewsListResponse reviewsListResponse = reviews.list("the.packagename.of.my.app").execute();
logger.info("review list response = " + reviewsListResponse.toPrettyString());
}
This worked.
I cannot test it yet, but I'm sure that fetching the billing information works as well:
private SubscriptionPurchase getPurchase() throws IOException
{
AndroidPublisher publisher = new AndroidPublisher.Builder(WebserverConfiguration.HTTP_TRANSPORT, WebserverConfiguration.JSON_FACTORY, configuration.getCredential()).setApplicationName("The name of my app on Google Play").build();
AndroidPublisher.Purchases purchases = publisher.purchases();
SubscriptionPurchase purchase = purchases.subscriptions().get("the.packagename.of.my.app", "subscriptionId", "billing token sent by the app").execute();
//do something or return
return purchase;
}
I have created a foreground service that gets user's geolocation after every 2 seconds the service than calculates the speed and performs some operation, the problem is application stops working after 24 hr and does not crash ( notification still in notification area remain ) and does not work in Oppo phones at all. Any help would be appreciated.
Thank you
Here is the code for my service
import android.app.KeyguardManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.Toast;
import org.json.JSONObject;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import java.io.File;
import java.io.FileWriter;
import java.util.Calendar;
import static java.lang.Math.acos;
import static java.lang.Math.cos;
import static java.lang.Math.sin;
public class drivingService extends Service implements LocationListener {
// Declaration of Initialized Variables
public static int PRIMARY_FOREGROUND_NOTIF_SERVICE_ID = 1001, //Declaration of integers
progress = 0;
public static boolean enabled = true, //Declaration of boolean flags
popupEnabled = false,
sent = false,
first = true,
locked = false,
removed = false,
popup_visible = false,
tmp_visible = false;
// Declaration of Uninitialized Variables
public static NotificationCompat.Builder notification;
private static String TAG = "LOCATION_THINGS"; //Declaration of strings
private static String id = "";
public int drive = 0,
stop = 0;
public double lat1, lat2, lng1, lng2;
public long time1, time2;
NotificationManager mNotificationManager;
NotificationManagerCompat cNotificationManager;
Database db;
WindowManager windowManager;
WindowManager.LayoutParams params;
private LocationManager mLocationManager = null; //Declaration of location manager
private ImageView popup, stopping;
boolean networkStatus;
//Returns true and false idf the device is locked or not
public static boolean isDeviceLocked(Context context) {
boolean isLocked = false;
// First we check the locked state
KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
boolean inKeyguardRestrictedInputMode = keyguardManager.inKeyguardRestrictedInputMode();
if (inKeyguardRestrictedInputMode) {
isLocked = true;
} else {
// If password is not set in the settings, the inKeyguardRestrictedInputMode() returns false,
// so we need to check if screen on for this case
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
isLocked = !powerManager.isInteractive();
} else {
//noinspection deprecation
isLocked = !powerManager.isScreenOn();
}
}
return isLocked;
}
//Create notification for service
public void createSimpleNotification() {
String GROUP_KEY_WORK_EMAIL = "com.blitzapp.textriteDriverAlert.not";
notification = new NotificationCompat.Builder(getApplicationContext(), id)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.large))
.setSmallIcon(R.drawable.not)
.setContentTitle("TextRite")
.setContentText("TextRite - Drive Mode is Enabled")
.setGroup(GROUP_KEY_WORK_EMAIL)
.setOngoing(false)
.setOnlyAlertOnce(true);
}
//Runs service powered by notification
public void renderNotification() {
cNotificationManager = NotificationManagerCompat.from(this);
cNotificationManager.notify(PRIMARY_FOREGROUND_NOTIF_SERVICE_ID, notification.build());
startForeground(PRIMARY_FOREGROUND_NOTIF_SERVICE_ID, notification.build());
}
//Creates Notification Channel
public void createNotificationChannel() {
id = "_channel_01";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel mChannel = new NotificationChannel(id, "TextRite - Drive Mode is Enabled", importance);
mChannel.enableLights(true);
mNotificationManager.createNotificationChannel(mChannel);
}
}
private void addToLogs(double speed, boolean alert, boolean tmp, boolean netwrok) {
try {
File root = new File(getFilesDir(), "speed_logs");
Log.d("Address", "" + getFilesDir());
if (!root.exists()) {
root.mkdir();
}
File filepath = new File(root, "logs.txt");
if (!filepath.exists()) {
filepath.createNewFile();
}
FileWriter writer = new FileWriter(filepath, true);
writer.append("Time->" + Calendar.getInstance().getTime() + "==|| Speed->" + speed + " || Alert Visible->" + alert + " || Temp Visible->" + tmp +"Network Status"+networkStatus+" || DB Count"+Database.dbCount+"\n");
writer.flush();
writer.close();
} catch (Exception ex) {
Log.e("File_I/O", "" + ex);
}
}
//Runs only once when the service is created
#Override
public void onCreate() {
Log.e(TAG, "onCreate");
try {
createNotificationChannel();
createSimpleNotification();
renderNotification();
} catch (Exception ex) {
Toast.makeText(this, "" + ex, Toast.LENGTH_LONG).show();
}
}
//Event Emitter to stop service
private void sendEvent() {
MainApplication application = (MainApplication) this.getApplication();
ReactNativeHost reactNativeHost = application.getReactNativeHost();
ReactInstanceManager reactInstanceManager = reactNativeHost.getReactInstanceManager();
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext != null) {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("stopService", null);
}
}
//This function is not used through out the code it is just added because of parent class service
#Override
public IBinder onBind(Intent arg0) {
return null;
}
//Adds alert to db when screen is locked
public void addAlert() {
try {
boolean networkStatus = isNetworkAvailable();
String alert = new Alert().getJsonObject();
db.insertAlert(alert);
if (networkStatus == true) {
db.sendData();
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "Some Error Occurred while sending alerts to server.", Toast.LENGTH_LONG).show();
}
}
//Runs every time the service is started
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
//Initialize database
db = new Database(getApplicationContext());
// Check If Force Stop button is presses
if (intent.getAction() != null && intent.getAction().equals("STOP")) {
stopForeground(true);
onDestroy();
} else {
// Check if switch is enabled then register location listener and create popup to render later
if (enabled) {
try {
getLocation();
createPopup();
//If any kind of mishap occurs report the user via toast message
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
// if switch not open by user then stop service
} else {
stopForeground(true);
onDestroy();
}
}
//If any kind of mishap occurs report the user via toast message
} catch (Exception ex) {
Toast.makeText(this, "Some Error Occurred while starting the service.", Toast.LENGTH_LONG).show();
}
return START_NOT_STICKY;
}
//Start the listener
private void getLocation() {
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
} catch (SecurityException ex) {
Toast.makeText(this, "Failed to request location update", Toast.LENGTH_LONG).show();
} catch (IllegalArgumentException ex) {
Toast.makeText(this, "GPS provider does not exist ", Toast.LENGTH_LONG).show();
}
}
//Take true or false in argument to render popup
public void clearAll() {
showTemp(false);
removed = true;
popupEnabled = false;
}
public void showPopup(boolean show) {
if (show == true) {
try {
stopping.setVisibility(View.INVISIBLE);
} catch (Exception e) {
}
popup.setVisibility(View.VISIBLE);
popup_visible = true;
popupEnabled = true;
} else {
popup.setVisibility(View.INVISIBLE);
popup_visible = false;
}
}
public void showTemp(boolean show) {
if (show == true) {
try {
popup.setVisibility(View.INVISIBLE);
} catch (Exception e) {
}
popupEnabled = true;
stopping.setVisibility(View.VISIBLE);
tmp_visible = true;
} else {
stopping.setVisibility(View.INVISIBLE);
tmp_visible = false;
}
}
//Creates popup or the alert window
private void createPopup() {
int LAYOUT_TYPE;
//Layout Parameters Declared
params = new WindowManager.LayoutParams();
//Setting Layout type According to build version of phone
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LAYOUT_TYPE = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_TYPE = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
}
//Setting Up Layout Type and other properties
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.MATCH_PARENT;
params.type = LAYOUT_TYPE;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
params.format = PixelFormat.TRANSLUCENT;
params.gravity = Gravity.CENTER;
params.x = 0;
params.y = 0;
//Check if Service is enabled by user then create popup set its visibility to false for later use
try {
if (enabled) {
//Window Manager Initialized
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
//Setting properties and parameters of popup to be viewed
popup = new ImageView(this);
popup.setImageResource(R.drawable.alert_potrait);
popup.setScaleType(ImageView.ScaleType.FIT_XY);
stopping = new ImageView(this);
stopping.setImageResource(R.drawable.stopping);
stopping.setScaleType(ImageView.ScaleType.FIT_XY);
windowManager.addView(popup, params);
windowManager.addView(stopping, params);
popup.setVisibility(View.INVISIBLE);
stopping.setVisibility(View.INVISIBLE);
}
//If any kind of mishap occurs report the user via toast message
} catch (Exception ex) {
Toast.makeText(this, "Some Error Occurred while creating Overlay Screen", Toast.LENGTH_LONG).show();
}
}
//Runs when is stopped
#Override
public void onDestroy() {
super.onDestroy();
try {
//set enabled service by user to false
enabled = false;
//disable popup visibility
popup.setVisibility(View.INVISIBLE);
//Unregister location manager for updates if it's not null
if (mLocationManager != null) {
mLocationManager.removeUpdates(this);
}
//send Event to React Native that service has stopped
sendEvent();
stopSelf();
} catch (Exception ex) {
Toast.makeText(getApplicationContext(), "Some Error Occurred, Restart your phone to avoid any inconvenience", Toast.LENGTH_LONG).show();
}
}
//Location Manager Initialization to access location listener
private void initializeLocationManager() {
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
//Returns true and false is network is connected or not
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
//Runs Every 2 second and returns the current location of the device
#Override
public void onLocationChanged(Location location) {
// check if location is not null or value is not a garbage value
if (location != null) {
//setting up variables to calculate speed
lat2 = lat1;
lng2 = lng1;
time2 = time1;
lat1 = location.getLatitude();
lng1 = location.getLongitude();
time1 = location.getTime();
//calculations performed
double distance = getDistance(lat1, lng1, lat2, lng2);
double time = calcTime(time1, time2);
double speed = distance / time;
Log.d("error: ",location.toString());
try {
networkStatus = isNetworkAvailable();
if (networkStatus == true) {
JSONObject log;
log = new JSONObject();
log.put("type","location_inside_if");
log.put("location_object",location.toString());
log.put("latitude",location.getLatitude());
log.put("longitude",location.getLongitude());
log.put("get_speed",speed);
log.put("speed_calculated",location.getSpeed());
log.put("drive",drive);
log.put("stop",stop);
log.put("locked",locked);
Log.d("Location_object", log.toString());
db.sendLogsData(log);
db.sendData();
}
} catch (Exception e) {
}
//if speed is greater than 8
if (speed >= 8) {
drive++;
stop = 0;
if (locked == true) {
locked = false;
showPopup(true);
} else {
if (drive == 5) {
showPopup(true);
drive = 0;
}
}
}
// if speed in less than 8
else {
drive = 0;
stop++;
popup.setVisibility(View.INVISIBLE);
if (locked == true) {
//Log.d("Log_Lock", "JUST AFTER UNLOCK: locked = true");
locked = false;
if (stop >= 25 && tmp_visible == true) {
if (tmp_visible) {
//Log.d("Log_Lock", "JUST AFTER UNLOCK: temp time up / back to normal");
clearAll();
stop = 0;
}
} else if (stop == 0) {
if (popup_visible) {
showTemp(true);
Log.d("Log_Lock", "JUST AFTER UNLOCK: timer running");
}
}
} else {
//Log.d("Log_Lock", "JUST AFTER UNLOCK: locked = false " + popupEnabled + " " + popup_visible + " " + tmp_visible);
if (popup_visible) {
//Log.d("Log_Lock", "AFTER SOMETIME: show temp popup");
showPopup(false);
showTemp(true);
drive = 0;
} else if (tmp_visible) {
showTemp(true);
if (stop >= 25) {
//Log.d("Log_Lock", "AFTER SOMETIME: temp time up");
clearAll();
stop = 0;
}
}
else{
clearAll();
}
}
}
if (isDeviceLocked(getApplicationContext())) {
popup.setVisibility(View.INVISIBLE);
stopping.setVisibility(View.INVISIBLE);
locked = true;
if (sent == false) {
addAlert();
sent = true;
}
} else {
sent = false;
}
}else{
try {
networkStatus = isNetworkAvailable();
if (networkStatus == true) {
JSONObject log;
log = new JSONObject();
log.put("type","inside_location_null");
log.put("location_object",location.toString());
log.put("drive",drive);
log.put("stop",stop);
log.put("locked",locked);
db.sendLogsData(log);
db.sendData();
}
} catch (Exception e) {
}
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
try {
networkStatus = isNetworkAvailable();
if (networkStatus == true) {
JSONObject log;
log = new JSONObject();
log.put("type","onStatusChanged");
log.put("provider",provider);
log.put("status",status);
log.put("extras",extras);
log.put("drive",drive);
log.put("stop",stop);
log.put("locked",locked);
db.sendLogsData(log);
}
} catch (Exception e) {
}
}
#Override
public void onProviderEnabled(String provider) {
try {
networkStatus = isNetworkAvailable();
if (networkStatus == true) {
JSONObject log;
log = new JSONObject();
log.put("type","onProviderEnabled");
log.put("provider",provider);
log.put("drive",drive);
log.put("stop",stop);
log.put("locked",locked);
db.sendLogsData(log);
}
} catch (Exception e) {
}
}
#Override
public void onProviderDisabled(String provider) {
try {
networkStatus = isNetworkAvailable();
if (networkStatus == true) {
JSONObject log;
log = new JSONObject();
log.put("type","onProviderDisabled");
log.put("provider",provider);
log.put("drive",drive);
log.put("stop",stop);
log.put("locked",locked);
db.sendLogsData(log);
}
} catch (Exception e) {
}
}
//Returns the distance between two locations
double getDistance(double lat1, double lon1, double lat2, double lon2) {
double M_PI = Math.PI;
// Convert degrees to radians
lat1 = lat1 * M_PI / 180.0;
lon1 = lon1 * M_PI / 180.0;
lat2 = lat2 * M_PI / 180.0;
lon2 = lon2 * M_PI / 180.0;
// radius of earth in metres
double r = 6378100;
// P
double rho1 = r * cos(lat1);
double z1 = r * sin(lat1);
double x1 = rho1 * cos(lon1);
double y1 = rho1 * sin(lon1);
// Q
double rho2 = r * cos(lat2);
double z2 = r * sin(lat2);
double x2 = rho2 * cos(lon2);
double y2 = rho2 * sin(lon2);
// Dot product
double dot = (x1 * x2 + y1 * y2 + z1 * z2);
double cos_theta = dot / (r * r);
double theta = acos(cos_theta);
// Distance in Metres
Log.d("Dist DISTANCE", Double.toString(r * theta));
return r * theta;
}
//Returns time in milliseconds between two locations
private double calcTime(double t1, double t2) {
Log.d("DIS_DIFF", Double.toString((t1 - t2) / 1000));
return (t1 - t2) / 1000;
}
}
I'm using sample demo of
https://github.com/aosp-mirror/platform_development/tree/master/samples/SipDemo
the programing is ok, it doesn´t show issues, but when I configure this, it shows message Registration failed.
I´m programing with android studio, and the server is asterisk.
I tried with soiper and and it works.
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
public String sipAddress = null;
public SipManager manager = null;
public SipProfile me = null;
public SipAudioCall call = null;
public IncomingCallReceiver callReceiver;
private static final int CALL_ADDRESS = 1;
private static final int SET_AUTH_INFO = 2;
private static final int UPDATE_SETTINGS_DIALOG = 3;
private static final int HANG_UP = 4;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_walkie_talkie);
ToggleButton pushToTalkButton = (ToggleButton) findViewById(R.id.pushToTalk);
pushToTalkButton.setOnTouchListener(this);
// Set up the intent filter. This will be used to fire an
// IncomingCallReceiver when someone calls the SIP address used by this
// application.
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
// "Push to talk" can be a serious pain when the screen keeps turning off.
// Let's prevent that.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
initializeManager();
}
#Override
public void onStart() {
super.onStart();
// When we get back from the preference setting Activity, assume
// settings have changed, and re-login with new auth info.
initializeManager();
}
#Override
public void onDestroy() {
super.onDestroy();
if (call != null) {
call.close();
}
closeLocalProfile();
if (callReceiver != null) {
this.unregisterReceiver(callReceiver);
}
}
public void initializeManager() {
if(manager == null) {
manager = SipManager.newInstance(this);
}
initializeLocalProfile();
}
/**
* Logs you into your SIP provider, registering this device as the location to
* send SIP calls to for your SIP address.
*/
public void initializeLocalProfile() {
if (manager == null) {
return;
}
if (me != null) {
closeLocalProfile();
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
/* String username = prefs.getString("namePref", "");
String domain = prefs.getString("domainPref", "");
String password = prefs.getString("passPref", ""); */
String username = "12";
String domain = "192.168.1.37";
String password = "1234";
if (username.length() == 0 || domain.length() == 0 || password.length() == 0) {
showDialog(UPDATE_SETTINGS_DIALOG);
return;
}
try {
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setAuthUserName("12");
builder.setDisplayName("12");
builder.setProfileName("12");
builder.setPassword(password);
me = builder.build();
Intent i = new Intent();
i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
manager.open(me, pi, null);
// This listener must be added AFTER manager.open is called,
// Otherwise the methods aren't guaranteed to fire.
manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
}
});
} catch (ParseException pe) {
updateStatus("Connection Error.");
} catch (SipException se) {
updateStatus("Connection error.");
}
}
/**
* Closes out your local profile, freeing associated objects into memory
* and unregistering your device from the server.
*/
public void closeLocalProfile() {
if (manager == null) {
return;
}
try {
if (me != null) {
manager.close(me.getUriString());
}
} catch (Exception ee) {
// Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee);
}
}
/**
* Make an outgoing call.
*/
public void initiateCall() {
updateStatus(sipAddress);
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is established.
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30);
}
catch (Exception e) {
// Log.i("WalkieTalkieActivity/InitiateCall", "Error when trying to close manager.", e);
if (me != null) {
try {
manager.close(me.getUriString());
} catch (Exception ee) {
// Log.i("WalkieTalkieActivity/InitiateCall",
// "Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
/**
* Updates the status box at the top of the UI with a messege of your choice.
* #param status The String to display in the status box.
*/
public void updateStatus(final String status) {
// Be a good citizen. Make sure UI changes fire on the UI thread.
this.runOnUiThread(new Runnable() {
public void run() {
TextView labelView = (TextView) findViewById(R.id.sipLabel);
labelView.setText(status);
}
});
}
/**
* Updates the status box with the SIP address of the current call.
* #param call The current, active call.
*/
public void updateStatus(SipAudioCall call) {
String useName = call.getPeerProfile().getDisplayName();
if(useName == null) {
useName = call.getPeerProfile().getUserName();
}
updateStatus(useName + "#" + call.getPeerProfile().getSipDomain());
}
/**
* Updates whether or not the user's voice is muted, depending on whether the button is pressed.
* #param v The View where the touch event is being fired.
* #param event The motion to act on.
* #return boolean Returns false to indicate that the parent view should handle the touch event
* as it normally would.
*/
public boolean onTouch(View v, MotionEvent event) {
if (call == null) {
return false;
} else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) {
call.toggleMute();
} else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) {
call.toggleMute();
}
return false;
}
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, CALL_ADDRESS, 0, "Call someone");
menu.add(0, SET_AUTH_INFO, 0, "Edit your SIP Info.");
menu.add(0, HANG_UP, 0, "End Current Call.");
return true;
}
}
Think that should be user#domain ...and an IP address is not a domain.
I had this error on my VoiSip Application
E/AudioRecord: AudioFlinger could not create record track, status: -1
E/AudioGroup: cannot initialize audio device
This error occurs after I'm trying to make call to another sip address
Here have 2 java class(WalkieTalkieActivity.java & IncomingCallReceiver.java)
WalkieTalkieActivity.java
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
public IncomingCallReceiver callReceiver;
public SipManager mSipManager = null;
public SipProfile mSipProfile = null;
public SipAudioCall call = null;
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_walkie_talkie);
ToggleButton pushToTalkButton = (ToggleButton) findViewById(R.id.pushToTalk);
pushToTalkButton.setOnTouchListener(this);
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
if (mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}
tv = (TextView)findViewById(R.id.textView);
}
#Override
public void onStart() {
super.onStart();
// When we get back from the preference setting Activity, assume
// settings have changed, and re-login with new auth info.
initializeManager();
}
#Override
public void onDestroy() {
super.onDestroy();
if (call != null) {
call.close();
}
closeLocalProfile();
if (callReceiver != null) {
this.unregisterReceiver(callReceiver);
}
}
public void closeLocalProfile() {
if (mSipManager == null) {
return;
}
try {
if (mSipProfile != null) {
mSipManager.close(mSipProfile.getUriString());
}
} catch (Exception ee) {
Log.d("onDestroy", "Failed to close local profile.", ee);
}
}
public void initializeManager() {
if(mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}
initializeLocalProfile();
}
private void initializeLocalProfile() {
String domain = "mydomain";
String username = "myusername";
String password = "mypassword";
try {
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
mSipProfile = builder.build();
if (mSipProfile == null){
Log.e("error cukimai", "null");
}else{
Log.e("error cukimai", "not null");
}
Intent i = new Intent();
i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
mSipManager.open(mSipProfile, pi, null);
mSipManager.setRegistrationListener(mSipProfile.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
Log.e("process","Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
Log.e("process","ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
Log.e("process","Registration failed. Please check settings.");
}
});
Log.e("process","stop");
} catch (SipException e) {
e.printStackTrace();
Log.e("error cukimai", "cuk cuk");
} catch (ParseException e) {
e.printStackTrace();
Log.e("error cukimai", "cuk");
}
}
public void updateStatus(final String st){
this.runOnUiThread(new Runnable() {
public void run() {
tv.setText(st);
}
});
}
public void updateStatus(SipAudioCall call) {
String useName = call.getPeerProfile().getDisplayName();
if(useName == null) {
useName = call.getPeerProfile().getUserName();
}
updateStatus(useName + "#" + call.getPeerProfile().getSipDomain());
}
public void callAct(View view) {
Toast.makeText(this, "about to make call", Toast.LENGTH_LONG).show();
makeCall();
}
public void makeCall(){
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is established.
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = mSipManager.makeAudioCall(mSipProfile.getUriString(), "sip:destination#domain", listener, 30);
Log.e("make call", "true");
start();
}catch (Exception e){
Log.i("error", "Error when trying to close manager.", e);
if (mSipProfile != null) {
try {
mSipManager.close(mSipProfile.getUriString());
} catch (Exception ee) {
Log.i("error", "Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
#Override
public boolean onTouch(View view, MotionEvent event) {
if (call == null) {
return false;
} else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) {
call.toggleMute();
} else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) {
call.toggleMute();
}
return false;
}
final MediaRecorder recorder = new MediaRecorder();
final String path;
/**
* Creates a new audio recording at the given path (relative to root of SD card).
*/
public WalkieTalkieActivity(String path) {
this.path = sanitizePath(path);
}
private String sanitizePath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.contains(".")) {
path += ".3gp";
}
return Environment.getExternalStorageDirectory().getAbsolutePath() + path;
}
/**
* Starts a new recording.
*/
public void start() throws IOException {
String state = android.os.Environment.getExternalStorageState();
if(!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
throw new IOException("SD Card is not mounted. It is " + state + ".");
}
// make sure the directory we plan to store the recording in exists
File directory = new File(path).getParentFile();
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Path to file could not be created.");
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(path);
recorder.prepare();
recorder.start();
}
/**
* Stops a recording that has been previously started.
*/
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
}
IncomingCallReceiver.java
public class IncomingCallReceiver extends BroadcastReceiver {
/**
* Processes the incoming call, answers it, and hands it over to the
* WalkieTalkieActivity.
* #param context The context under which the receiver is running.
* #param intent The intent being received.
*/
#Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (Exception e) {
e.printStackTrace();
}
}
};
WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context;
incomingCall = wtActivity.mSipManager.takeAudioCall(intent, listener);
incomingCall.answerCall(30);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
if(incomingCall.isMuted()) {
incomingCall.toggleMute();
}
wtActivity.call = incomingCall;
wtActivity.updateStatus(incomingCall);
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}
}
I'm really new on Sip and Voip Implementing in Android Studio. I got this code from google source code.
I believe this error occurs because of the use of hardware (audio). However I have been searching on google for almost 1 week and not giving results. Can someone help me?
I had same problem but when i changed targetSdkVersion to 12 in build.gradel its fixed.
and this answer helped me to fixed problem .
You must choose the BufferSize when you want to record or call in app. For example:
int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
if (bufferSize > 0 && bufferSize <= 256){
bufferSize = 256;
}else if (bufferSize > 256 && bufferSize <= 512){
bufferSize = 512;
}else if (bufferSize > 512 && bufferSize <= 1024){
bufferSize = 1024;
}else if (bufferSize > 1024 && bufferSize <= 2048){
bufferSize = 2048;
}else if (bufferSize > 2048 && bufferSize <= 4096){
bufferSize = 4096;
}else if (bufferSize > 4096 && bufferSize <= 8192){
bufferSize = 8192;
}else if (bufferSize > 8192 && bufferSize <= 16384){
bufferSize = 16384;
}else{
bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
}
I am using a PHP MySQL server model. I want to decode the JSON data that is sent to the server by this code. Any help would be appreciated. The app sends current GPS coordinates to inputed server as JSON array object. I would like to decode it to share with other android users. Thanks a lot. This is the Android code.
public class TrackerService extends Service {
private static final String TAG = "TripTracker/Service";
private final String updatesCache = "updates.cache";
public static TrackerService service;
private NotificationManager nm;
private Notification notification;
private static boolean isRunning = false;
private String freqString;
private int freqSeconds;
private String endpoint;
private final int MAX_RING_SIZE = 15;
private LocationListener locationListener;
private AlarmManager alarmManager;
private PendingIntent pendingAlarm;
private static volatile PowerManager.WakeLock wakeLock;
private AsyncTask httpPoster;
ArrayList<LogMessage> mLogRing = new ArrayList<LogMessage>();
ArrayList<Messenger> mClients = new ArrayList<Messenger>();
ArrayList<List> mUpdates = new ArrayList<List>();
final ReentrantReadWriteLock updateLock = new ReentrantReadWriteLock();
final Messenger mMessenger = new Messenger(new IncomingHandler());
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
static final int MSG_LOG = 3;
static final int MSG_LOG_RING = 4;
#Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
#Override
public void onCreate() {
super.onCreate();
TrackerService.service = this;
endpoint = Prefs.getEndpoint(this);
freqSeconds = 0;
freqString = null;
freqString = Prefs.getUpdateFreq(this);
if (freqString != null && !freqString.equals("")) {
try {
Pattern p = Pattern.compile("(\\d+)(m|h|s)");
Matcher m = p.matcher(freqString);
m.find();
freqSeconds = Integer.parseInt(m.group(1));
if (m.group(2).equals("h"))
freqSeconds *= (60 * 60);
else if (m.group(2).equals("m"))
freqSeconds *= 60;
}
catch (Exception e) {
}
}
if (endpoint == null || endpoint.equals("")) {
logText("invalid endpoint, stopping service");
stopSelf();
}
if (freqSeconds < 1) {
logText("invalid frequency (" + freqSeconds + "), stopping " +
"service");
stopSelf();
}
readCache();
showNotification();
isRunning = true;
/* we're not registered yet, so this will just log to our ring buffer,
* but as soon as the client connects we send the log buffer anyway */
logText("service started, requesting location update every " +
freqString);
/* findAndSendLocation() will callback to this */
locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
sendLocation(location);
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {
}
};
/* we don't need to be exact in our frequency, try to conserve at least
* a little battery */
alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent i = new Intent(this, AlarmBroadcast.class);
pendingAlarm = PendingIntent.getBroadcast(this, 0, i, 0);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(), freqSeconds * 1000, pendingAlarm);
}
#Override
public void onDestroy() {
super.onDestroy();
if (httpPoster != null)
httpPoster.cancel(true);
try {
LocationManager locationManager = (LocationManager)
this.getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(locationListener);
}
catch (Exception e) {
}
/* kill persistent notification */
nm.cancelAll();
if (pendingAlarm != null)
alarmManager.cancel(pendingAlarm);
isRunning = false;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
/* must be done inside of updateLock */
public void cacheUpdates() {
OutputStreamWriter cacheStream = null;
try {
FileOutputStream cacheFile = TrackerService.this.openFileOutput(
updatesCache, Activity.MODE_PRIVATE);
cacheStream = new OutputStreamWriter(cacheFile, "UTF-8");
/* would be nice to just serialize mUpdates but it's not
* serializable. create a json array of json objects, each object
* having each key/value pair of one location update. */
JSONArray ja = new JSONArray();
for (int i = 0; i < mUpdates.size(); i++) {
List<NameValuePair> pair = mUpdates.get(i);
JSONObject jo = new JSONObject();
for (int j = 0; j < pair.size(); j++) {
try {
jo.put(((NameValuePair)pair.get(j)).getName(),
pair.get(j).getValue());
}
catch (JSONException e) {
}
}
ja.put(jo);
}
cacheStream.write(ja.toString());
cacheFile.getFD().sync();
}
catch (IOException e) {
Log.w(TAG, e);
}
finally {
if (cacheStream != null) {
try {
cacheStream.close();
}
catch (IOException e) {
}
}
}
}
/* read json cache into mUpdates */
public void readCache() {
updateLock.writeLock().lock();
InputStreamReader cacheStream = null;
try {
FileInputStream cacheFile = TrackerService.this.openFileInput(
updatesCache);
StringBuffer buf = new StringBuffer("");
byte[] bbuf = new byte[1024];
int len;
while ((len = cacheFile.read(bbuf)) != -1)
buf.append(new String(bbuf));
JSONArray ja = new JSONArray(new String(buf));
mUpdates = new ArrayList<List>();
for (int j = 0; j < ja.length(); j++) {
JSONObject jo = ja.getJSONObject(j);
List<NameValuePair> nvp = new ArrayList<NameValuePair>(2);
Iterator<String> i = jo.keys();
while (i.hasNext()) {
String k = (String)i.next();
String v = jo.getString(k);
nvp.add(new BasicNameValuePair(k, v));
}
mUpdates.add(nvp);
}
if (mUpdates.size() > 0)
logText("read " + mUpdates.size() + " update" +
(mUpdates.size() == 1 ? "" : "s") + " from cache");
}
catch (JSONException e) {
}
catch (FileNotFoundException e) {
}
catch (IOException e) {
Log.w(TAG, e);
}
finally {
if (cacheStream != null) {
try {
cacheStream.close();
}
catch (IOException e) {
}
}
}
updateLock.writeLock().unlock();
}
/* called within wake lock from broadcast receiver, but assert that we have
* it so we can keep it longer when we return (since the location request
* uses a callback) and then free it when we're done running through the
* queue */
public void findAndSendLocation() {
if (wakeLock == null) {
PowerManager pm = (PowerManager)this.getSystemService(
Context.POWER_SERVICE);
/* we don't need the screen on */
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"triptracker");
wakeLock.setReferenceCounted(true);
}
if (!wakeLock.isHeld())
wakeLock.acquire();
LocationManager locationManager = (LocationManager)
this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER,
locationListener, null);
}
public static boolean isRunning() {
return isRunning;
}
private void showNotification() {
nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notification = new Notification(R.drawable.icon,
"Trip Tracker Started", System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
notification.setLatestEventInfo(this, "Trip Tracker",
"Sending location every " + freqString, contentIntent);
notification.flags = Notification.FLAG_ONGOING_EVENT;
nm.notify(1, notification);
}
private void updateNotification(String text) {
if (nm != null) {
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
notification.setLatestEventInfo(this, "Trip Tracker", text,
contentIntent);
notification.when = System.currentTimeMillis();
nm.notify(1, notification);
}
}
public void logText(String log) {
LogMessage lm = new LogMessage(new Date(), log);
mLogRing.add(lm);
if (mLogRing.size() > MAX_RING_SIZE)
mLogRing.remove(0);
updateNotification(log);
for (int i = mClients.size() - 1; i >= 0; i--) {
try {
Bundle b = new Bundle();
b.putString("log", log);
Message msg = Message.obtain(null, MSG_LOG);
msg.setData(b);
mClients.get(i).send(msg);
}
catch (RemoteException e) {
/* client is dead, how did this happen */
mClients.remove(i);
}
}
}
/* flatten an array of NameValuePairs into an array of
* locations[0]latitude, locations[1]latitude, etc. */
public List<NameValuePair> getUpdatesAsArray() {
List<NameValuePair> pairs = new ArrayList<NameValuePair>(2);
for (int i = 0; i < mUpdates.size(); i++) {
List<NameValuePair> pair = mUpdates.get(i);
for (int j = 0; j < pair.size(); j++)
pairs.add(new BasicNameValuePair("locations[" + i + "][" +
((NameValuePair)pair.get(j)).getName() + "]",
pair.get(j).getValue()));
}
return pairs;
}
public int getUpdatesSize() {
return mUpdates.size();
}
public void removeUpdate(int i) {
mUpdates.remove(i);
}
private void sendLocation(Location location) {
List<NameValuePair> pairs = new ArrayList<NameValuePair>(2);
pairs.add(new BasicNameValuePair("time",
String.valueOf(location.getTime())));
pairs.add(new BasicNameValuePair("latitude",
String.valueOf(location.getLatitude())));
pairs.add(new BasicNameValuePair("longitude",
String.valueOf(location.getLongitude())));
pairs.add(new BasicNameValuePair("speed",
String.valueOf(location.getSpeed())));
/* push these pairs onto the queue, and only run the poster if another
* one isn't running already (if it is, it will keep running through
* the queue until it's empty) */
updateLock.writeLock().lock();
mUpdates.add(pairs);
int size = service.getUpdatesSize();
cacheUpdates();
updateLock.writeLock().unlock();
logText("location " +
(new DecimalFormat("#.######").format(location.getLatitude())) +
", " +
(new DecimalFormat("#.######").format(location.getLongitude())) +
(size <= 1 ? "" : " (" + size + " queued)"));
if (httpPoster == null ||
httpPoster.getStatus() == AsyncTask.Status.FINISHED)
(httpPoster = new HttpPoster()).execute();
}
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
/* respond with our log ring to show what we've been up to */
try {
Message replyMsg = Message.obtain(null, MSG_LOG_RING);
replyMsg.obj = mLogRing;
msg.replyTo.send(replyMsg);
}
catch (RemoteException e) {
}
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
break;
default:
super.handleMessage(msg);
}
}
}
/* Void as first arg causes a crash, no idea why
E/AndroidRuntime(17157): Caused by: java.lang.ClassCastException: java.lang.Object[] cannot be cast to java.lang.Void[]
*/
class HttpPoster extends AsyncTask<Object, Void, Boolean> {
#Override
protected Boolean doInBackground(Object... o) {
TrackerService service = TrackerService.service;
int retried = 0;
int max_retries = 4;
while (true) {
if (isCancelled())
return false;
boolean failed = false;
updateLock.writeLock().lock();
List<NameValuePair> pairs = service.getUpdatesAsArray();
int pairSize = service.getUpdatesSize();
updateLock.writeLock().unlock();
AndroidHttpClient httpClient =
AndroidHttpClient.newInstance("TripTracker");
try {
HttpPost post = new HttpPost(endpoint);
post.setEntity(new UrlEncodedFormEntity(pairs));
HttpResponse resp = httpClient.execute(post);
int httpStatus = resp.getStatusLine().getStatusCode();
if (httpStatus == 200) {
/* all good, we can remove everything we've sent from
* the queue (but not just clear it, in case another
* one jumped onto the end while we were here) */
updateLock.writeLock().lock();
for (int i = pairSize - 1; i >= 0; i--)
service.removeUpdate(i);
updateLock.writeLock().unlock();
}
else {
logText("POST failed to " + endpoint + ": got " +
httpStatus + " status");
failed = true;
}
}
catch (Exception e) {
logText("POST failed to " + endpoint + ": " + e);
Log.w(TAG, e);
failed = true;
}
finally {
if (httpClient != null)
httpClient.close();
}
if (failed) {
/* if our initial request failed, snooze for a bit and try
* again, the server might not be reachable */
SystemClock.sleep(15 * 1000);
if (++retried > max_retries) {
/* give up since we're holding the wake lock open for
* too long. we'll get it next time, champ. */
logText("too many failures, retrying later (queue " +
"size " + service.getUpdatesSize() + ")");
break;
}
}
else
retried = 0;
int q = 0;
updateLock.writeLock().lock();
q = service.getUpdatesSize();
cacheUpdates();
updateLock.writeLock().unlock();
if (q == 0)
break;
/* otherwise, run through the rest of the queue */
}
return false;
}
protected void onPostExecute(Boolean b) {
if (wakeLock != null && wakeLock.isHeld())
wakeLock.release();
}
}
}
You can decode the data using json_decode()
<?php
$json = ""; // JSON data
$json_obj = json_decode($json); // As Object
$json_arr = json_decide($json,true) // As Array
var_dump($json_obj);
print_r($json_arr);
// Store Array to database using serialize function
$data = serialize($json_array); // Array will be converted into string
?>