How to display duration using Google Maps? - android

I am trying to display to the user just the duration between two locations using latitude and longitude. I am having trouble with permissions which I am not sure how to handle it.
Here is my doInBackground code:
protected String[] doInBackground(String... params) {
try {
LocationManager locationManager = (LocationManager) MyCustomHomeActivity.this
.getSystemService(LOCATION_SERVICE);
// getting GPS status
boolean isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
boolean isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
} else {
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
String shuLat = "41.2207188";
String shuLong = "-73.24168179999999";
String forecastJsonStr = null;
String myUrlSetup = "https://maps.googleapis.com/maps/api/directions/json?origin="+latitude + "," + longitude +"&destination="+shuLat +"," + shuLong + "&departure_time=now&traffic_model=best_guess&key=AIzaSyB6l8vrnspw2-1Q_cnzO03JlAsIOMl-7bs";
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
try {
URL url;
url = new URL(myUrlSetup);
// Create the request to GoogleMapAPI, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
System.out.println("I am in doInBackground step3");
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
forecastJsonStr = buffer.toString();
Log.v(LOG_TAG, "Forecast string: " + forecastJsonStr);
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
try {
System.out.println("I am just in front of calling getDurationDataFromJson");
return getDurationDataFromJson(forecastJsonStr);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return new String[0];
}//end doInBackground
Here is my getDurationDataFromJSON code:
private String[] getDurationDataFromJson(String forecastJsonStr)
throws JSONException {
// These are the names of the JSON objects that need to be extracted.
final String OWM_ROUTES = "routes";
final String OWM_LEGS = "legs";
final String OWM_DURATION = "duration";
final String OWM_TEXT = "text";
String[] resultStrs = new String[0];
String duration;
JSONObject durationJson = new JSONObject(forecastJsonStr);
JSONArray routeArray = durationJson.getJSONArray(OWM_ROUTES);
JSONArray legArray = routeArray.getJSONObject(0).getJSONArray(OWM_LEGS);
//Duration
JSONObject durationObj = legArray.getJSONObject(0).getJSONObject(OWM_DURATION);
duration = durationObj.getString(OWM_TEXT);
resultStrs[0] = duration;
System.out.println("Duration is: " + duration);
for (String s : resultStrs) {
System.out.println("Duration entry: " + s);
Log.v(LOG_TAG, "Duration entry: " + s);
}
return resultStrs;
}
Trouble I am facing is the following part in doInBackGround code:
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Error is:
Call requires permission which may be rejected by user: code should explicitly check to see if permission is available(with `check permission`) or explicitly handle a potential `SecurityException`.
I am not sure if I am going in the right direction. Please guide me through this.

With Android API level (23), permissions are requested at running time, here you have de official documentation:
https://developer.android.com/training/permissions/requesting.html
Basically, you need to check if the device Android API level is >= 23, and if so, request the required permissions. Try something like this:
if ( Build.VERSION.SDK_INT >= 23)
//Ask for needed permissions following the docs mentioned above
}
I hope this helps!

I will suggest you to use FusedLocationProviderApi
to get last known location.
But before doing anything with location you need make sure that you have provided
android.permission.ACCESS_COARSE_LOCATION
android.permission.ACCESS_FINE_LOCATION
in your manifest.xml.
Now I came to your point. From API Level-23 android indrouces explicit permission seeking feature. To provide this you need to follow some steps.
I hereby attach some code blocks for your help-
Checker of required permission states and device location service
public boolean isLocationEnabled() {
int locationMode = 0;
String locationProviders;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
return locationMode != Settings.Secure.LOCATION_MODE_OFF;
} else {
locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
return !TextUtils.isEmpty(locationProviders);
}
}
public boolean hasCoarseLocationPermission() {
return ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
public boolean hasFineLocationPermission() {
return ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
Now launch your activity/fragment after checking and providing expicit permission
private void initiateYourActivityCallAfterCheckingPermission() {
if (hasCoarseLocationPermission() && hasFineLocationPermission()) {
if (locationUtil.isLocationEnabled()) {
startYourLocationActivity();
}
} else if (!hasFineLocationPermission() && hasCoarseLocationPermission()) {
requestBothLocationPermission();
} else if (hasFineLocationPermission() && hasCoarseLocationPermission()) {
requestFineLocationPermission();
} else if (hasFineLocationPermission() && !hasCoarseLocationPermission()) {
requestCoarseLocationPermission();
}
}
private void requestBothLocationPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(SplashActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)
&& ActivityCompat.shouldShowRequestPermissionRationale(SplashActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)) {
} else {
ActivityCompat.requestPermissions(SplashActivity.this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_BOTH_LOCATION);
}
}
private void requestCoarseLocationPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(SplashActivity.this,
Manifest.permission.ACCESS_COARSE_LOCATION)) {
} else {
ActivityCompat.requestPermissions(SplashActivity.this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_COARSE_LOCATION);
}
}
private void requestFineLocationPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(SplashActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
} else {
ActivityCompat.requestPermissions(SplashActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION);
}
}
/**
* to process permission result
*/
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case General.REQUEST_BOTH_LOCATION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
startYourLocationActivity();
}
break;
case General.REQUEST_COARSE_LOCATION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startYourLocationActivity();
}
break;
case General.REQUEST_FINE_LOCATION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startYourLocationActivity();
}
break;
}
}
Hope this will help.

Related

android app permissions is not asking properly

public class EEmployeeApplication extends Application {
public void onCreate() {
super.onCreate();
try {
mContext = getApplicationContext();
dbHandler = new DataBaseModule(this);
dbHandler.getReadableDatabase();
dbHandler.close();
dbHandler = getDbHandler();
curUser = dbHandler.getActiveUserInfo();
eEMPSharedPreference = new eEmployeeSharedPreference();
DataSyncStartAlarm newAlarm = new DataSyncStartAlarm();
newAlarm.startDataSyncAlarm(mContext, null);
} catch (Exception e) {
Log.d("eEmp/Application ", e.toString());
}
}
#Override
public void onTerminate() {
try {
} catch (Exception e) {
Log.d("eEmp/Application ", e.toString());
}
super.onTerminate();
}
public static boolean isNetAvailable() {
try {
ConnectivityManager connectivity = (ConnectivityManager)
mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
{
NetworkInfo netInfo = connectivity.getActiveNetworkInfo();
if (netInfo != null) {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if ((info == null) || (!netInfo.isConnectedOrConnecting())) {
return false;
} else {
return true;
}
}
}
return false;
} catch (Exception e) {
Log.d("eEmp/Application", e.toString());
return false;
}
}
public DataBaseModule getDbHandler() {
return dbHandler;
}
public void checkUserAvailability(Activity activity) {
try {
if (curUser == null) // No Employee registered in local DB
{
activity.finish();
Intent loginScreen = new Intent(mContext, Login_Activity.class);
loginScreen.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
loginScreen.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(loginScreen);
} else {
activity.finish();
List<EmpZonesResponseDTO> empZonesResponseDTOS ;
empZonesResponseDTOS = eEMPSharedPreference.getZones(mContext);
if (empZonesResponseDTOS == null){
Intent dashboardAct = new Intent(mContext, Login_Activity.class);
dashboardAct.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
dashboardAct.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(dashboardAct);
}else {
Intent dashboardAct = new Intent(mContext, NavigationActivity.class);
dashboardAct.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
dashboardAct.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(dashboardAct);
}
}
} catch (Exception except) {
Log.d("eEmp/LoginActivity", except.toString());
}
}
public static Context getContext() {
return mContext;
}
public void SyncMasterData(NavigationActivity NavActivity) {
try{
if (isNetAvailable()) {
Log.d("eEmp/LoginCheck", "Internet is available");
SyncMasterDataDownloadTask SyncTask = new SyncMasterDataDownloadTask();
SyncTask.setContextandActivity(this,NavActivity);
SyncTask.execute();
} else
{
Log.d("eEmp/SyncMasterData", "Internet is not available");
NavActivity.DismissMasterDataDownload();
Snackbar
.make(NavActivity.navigationView,
"No Internet connection, Unable to Sync Account", Snackbar.LENGTH_LONG)
.show();
}
}catch (Exception e){
e.printStackTrace();
}
}
public String getActivityFragmentTag(EmpConstants.WorkType aSelectedWorkType) {
String selectedTag;
switch (aSelectedWorkType) {
case Dashboard:
selectedTag = EmpConstants.DashBoard_Info_Tag;
break;
case Profile:
selectedTag = EmpConstants.Personal_Info_Tag;
break;
case Entry:
selectedTag = EmpConstants.Entry_Info_Tag;
break;
case Plan:
selectedTag = EmpConstants.Plan_Info_Tag;
break;
case Report:
selectedTag = EmpConstants.Report_Info_Tag;
break;
case QR:
selectedTag = EmpConstants.QR_Info_Tag;
break;
case Miscellaneous:
selectedTag = EmpConstants.Miscellaneous_Info_Tag;
break;
case Nothing:
selectedTag = "";
break;
default:
selectedTag = "";
break;
}
return selectedTag;
}
// Location Method
public GpsLocationListener getGpsLocationListener() {
try {
if (gpsLocationListener == null) {
gpsLocationListener = new GpsLocationListener();
gpsLocationListener.getGPSCordinates();
//Log.d("eEmp/getGPSLocationList","Location Listener Created");
}
} catch (Exception gpsLocationExp) {
Log.d("eEmp/getGPSLocationList", "Error raised due to " + gpsLocationExp.toString());
}
return gpsLocationListener;
}
public String getEmpImageDirPath() {
try {
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()
+ EmpConstants.appDir;
} catch (Exception e) {
Log.d("eEmp/ImgDir", e.toString());
return "";
}
}
public String getEmpThumbImageDirPath() {
try {
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()
+ EmpConstants.thumbnailDir;
} catch (Exception e) {
Log.d("eEmp/ThumbImgDir", e.toString());
return "";
}
}
public Bitmap loadFromFile(String filename) {
try {
File f = new File(filename);
if (!f.exists()) {
return null;
}
final int width = EmpConstants.DisplayWidth;//mDisplay.widthPixels;
final int height = EmpConstants.DisplayHeight;//mDisplay.heightPixels;
Bitmap tmp = decodeSampledBitmapFromResource(filename, width, height);
return tmp;
} catch (Exception e) {
return null;
}
}
public static Bitmap decodeSampledBitmapFromResource(String imgFile,
int reqWidth, int reqHeight) {
try {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imgFile, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(imgFile, options);
} catch (Exception sampleBitmapConvExp) {
Log.d("eEmp/sampleBMPConv", "Error raised due to " + sampleBitmapConvExp.toString());
return null;
}
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public void checkImageDirectories() {
try {
File eEmpPhotosDir = new File(getEmpImageDirPath());
if (!eEmpPhotosDir.exists()) {
eEmpPhotosDir.mkdir();
}
File eEmpThumbPhotosDir = new File(getEmpThumbImageDirPath());
if (!eEmpThumbPhotosDir.exists())
eEmpThumbPhotosDir.mkdir();
} catch (Exception e) {
Log.d("eEmp/CheckDir", e.toString());
}
}
public void showFullImage(Context context, String curImgFile) {
try {
if (curImgFile.length() != 0) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
final Dialog nagDialog = new Dialog(context, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
nagDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
nagDialog.setCancelable(false);
nagDialog.setContentView(R.layout.preview_image);
Button btnClose = (Button) nagDialog.findViewById(R.id.btnIvClose);
ImageView ivPreview = (ImageView) nagDialog.findViewById(R.id.iv_preview_image);
TextView tvLoading = (TextView) nagDialog.findViewById(R.id.tvImgLoading);
ivPreview.setTag(tvLoading);
ImageRequest imgOrgReq = new ImageRequest();
imgOrgReq.imgView = ivPreview;
imgOrgReq.ImgType = EmpConstants.ImageLoadingType.OriginalImage;
imgOrgReq.context = (EEmployeeApplication) mContext;
BitmapWorkerTask statusImg = new BitmapWorkerTask(imgOrgReq);
statusImg.execute(curImgFile);
btnClose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
nagDialog.dismiss();
}
});
nagDialog.show();
}
} catch (Exception e) {
Log.d("eEmp/ShowFullImg", e.getLocalizedMessage());
}
}
// delete selected image from external storage
public void deleteSelImgFromStorage(String imgPath, Context context) {
try {
File imgFile = new File(imgPath);
if (imgPath.contains(EmpConstants.appName)) {
if (imgFile.exists()) {
imgFile.delete();
}
MediaScannerConnection.scanFile(context, new String[]{imgPath}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
}
});
}
} catch (Exception e) {
Log.i("Delete image", e.toString());
}
}
// For Marshmallow
// To Check permissions for Marshmallow
public List<String> askPermissions(ArrayList<EmpConstants.PermissionsList> ReqPermnsList) {
List<String> permissionsNeeded = new ArrayList<String>();
for (EmpConstants.PermissionsList perm : ReqPermnsList) {
switch (perm) {
case PhonePerm:
if (addPermission(Manifest.permission.READ_PHONE_STATE))
permissionsNeeded.add(Manifest.permission.READ_PHONE_STATE);
break;
case External_StoragePerm:
if (addPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE))
permissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (addPermission(Manifest.permission.READ_EXTERNAL_STORAGE))
permissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE);
break;
case LocationPerm:
if (addPermission(Manifest.permission.ACCESS_COARSE_LOCATION))
permissionsNeeded.add(Manifest.permission.ACCESS_COARSE_LOCATION);
if (addPermission(Manifest.permission.ACCESS_FINE_LOCATION))
permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
break;
case CameraPerm:
if (addPermission(Manifest.permission.CAMERA))
permissionsNeeded.add(Manifest.permission.CAMERA);
break;
}
}
return permissionsNeeded;
}
public boolean addPermission(String permission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
return true;
}
}
return false;
}
public boolean isAnyPermissionRequired(ArrayList<EmpConstants.PermissionsList> ReqPermnsList) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
try {
if (ReqPermnsList.size() == 0) {
return false;
} else {
for (EmpConstants.PermissionsList perm : ReqPermnsList) {
switch (perm) {
case PhonePerm:
if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_DENIED) {
return true;
}
break;
case External_StoragePerm:
if ((checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED)
|| (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED)) {
return true;
}
break;
case LocationPerm:
if ((checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_DENIED)
|| (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED)) {
return true;
}
break;
case CameraPerm:
if ((checkSelfPermission(Manifest.permission.CAMERA)== PackageManager.PERMISSION_DENIED)){
return true;
}
break;
default:
return false;
}
}
return false;
}
} catch (Exception checkPermExpt) {
Log.d("eEmp/CheckPerms", "Exception due to " + checkPermExpt.toString());
}
}
return false;
}
public void getNetworkProvideLocation() {
try {
if (longitude_Value == 0 || latitude_Value == 0) {
LocationManager locationManager = (LocationManager) EEmployeeApplication.getContext().getSystemService(Context.LOCATION_SERVICE);
boolean isNetworkEnable = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (isNetworkEnable) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Location lastLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (lastLocation != null) {
longitude_Value = lastLocation.getLongitude();
latitude_Value = lastLocation.getLatitude();
Log.d("eEmp/getNwValues", "Network Coordinates Updated" );
}
} else {
return;
}
}
} catch (Exception networkLocExp) {
Log.d("eEmp/getNwValues", "Exception due to " + networkLocExp.toString());
}
public int isValidUser() {
try {
if (isNetAvailable()) {
HTTPCommunication loginHTTPRequest;
EEmployeeHTTPResponse result;
if (curUser != null) {
Log.d("eEmp/ValLogin", "Validating User in Background");
loginHTTPRequest = new HTTPCommunication();
EmployeeInfoDTO loginInfo = new EmployeeInfoDTO();
loginHTTPRequest.setRequestType(EmpConstants.HTTPRequestType.NewUser);
loginInfo.EMPID = curUser.getEMPID();
loginInfo.Password = curUser.getPassword();
result = loginHTTPRequest.SendHTTPRequest(loginInfo);
if (result != null) {
if (result.HTTPStatusCode == 200) {
if (result.Data != null) {
return result.Data.ResponseCode;
}
}
}
}
}
return 0; // Invalid User
} catch (Exception e) {
Log.d("eEmp/ValLoginError", e.toString());
return 0;
}
}
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
LaunchingActivity.java
public class LaunchingActivity extends Activity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, OnTaskStateChange {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
setContentView(R.layout.activity_launching);
context = (EEmployeeApplication) EEmployeeApplication.getContext();
if (EEmployeeApplication.isNetAvailable()){
// Read IMEI Number
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList<EmpConstants.PermissionsList> reqPermissionsList = new ArrayList<>();
if ((context.eEMPSharedPreference != null) && (context.eEMPSharedPreference.getIMEI().isEmpty())) {
reqPermissionsList.add(EmpConstants.PermissionsList.PhonePerm);
}
reqPermissionsList.add(EmpConstants.PermissionsList.External_StoragePerm);
reqPermissionsList.add(EmpConstants.PermissionsList.LocationPerm);
reqPermissionsList.add(EmpConstants.PermissionsList.CameraPerm);
// Check All Permissions
if (context.isAnyPermissionRequired(reqPermissionsList)) {
requestPermission(context.askPermissions(reqPermissionsList));
} else {
readIMEINumber();
}
} else {
readIMEINumber();
}
int x = BuildConfig.VERSION_CODE;
AppVersionTask mTask = new AppVersionTask();
mTask.setListener(this);
APPVERREQ aRequest = new APPVERREQ();
aRequest.requestType = EmpConstants.HTTPRequestType.App_Ver;
APP_VERSION loginInfo = new APP_VERSION();
loginInfo.APP_VER = BuildConfig.VERSION_NAME;
aRequest.RequestObj = loginInfo;
mTask.execute(aRequest);
}
try {
Log.d("eEmp/Test", "MasterdataTaskStarted");
MasterDataLoadTask masterDataLoadTask = new MasterDataLoadTask();
masterDataLoadTask.setContextandActivity(context, this);
masterDataLoadTask.execute();
} catch (Exception MasterDataExcept) {
Log.d("eEmp/MstrDataTask", "Exception Occurred due to " + MasterDataExcept.toString());
context.checkUserAvailability(this);
}
Log.d("eEmp/LaunchCreate", "Launching Created");
} catch (Exception e) {
Log.d("eEmp/LaunchActvty", e.toString());
}
}
#Override
protected void onStart() {
super.onStart();
if ((mGoogleApiClient != null) && (!mGoogleApiClient.isConnected())) {
mGoogleApiClient.connect();
}
Log.d("eEMP/LaunchOnStart", "Launch OnStart");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
// For Marshmallow
// To Check permissions for Marshmallow
public void requestPermission(List<String> permissionsNeeded) {
if (permissionsNeeded.size() > 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissionsNeeded.toArray(new String[permissionsNeeded.size()]),
EmpConstants.REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
readIMEINumber();
}
// The callback for the management of the user settings regarding location
private ResultCallback<LocationSettingsResult> mResultCallbackFromSettings = new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// GPS is already in On State
initiateLocationRequest();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
status.startResolutionForResult(
LaunchingActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
default:
context.checkUserAvailability(LaunchingActivity.this);
Log.e("eEmp/Location", "Settings change unavailable. We have no way to fix the settings so we won't show the dialog.");
break;
}
}
};
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
try {
switch (requestCode) {
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
if (mGoogleApiClient.isConnected()) {
initiateLocationRequest();
}
break;
case Activity.RESULT_CANCELED:
context.checkUserAvailability(this);
break;
default:
break;
}
break;
}
} catch (Exception expt) {
Log.d("eEmp/AcvtResult", "Exception occurred due to " + expt.toString());
}
}
public void readIMEINumber() {
try {
if ((context.eEMPSharedPreference != null) && (context.eEMPSharedPreference.getIMEI().isEmpty())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
context.eEMPSharedPreference.setIMEI(telephonyManager.getDeviceId());
}
} else {
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
context.eEMPSharedPreference.setIMEI(telephonyManager.getDeviceId());
}
}
if (!checkGPSStatus()) {
LocationRequest mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (checkPlayServices()) {
LocationSettingsRequest.Builder locationSettingsRequestBuilder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
locationSettingsRequestBuilder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, locationSettingsRequestBuilder.build());
result.setResultCallback(mResultCallbackFromSettings);
} else {
context.checkUserAvailability(this);
}
} else {
initiateLocationRequest();
}
} catch (Exception IMEIExp) {
Log.d("eEmp/IMEIGet", "Unable to get IMEI number due to " + IMEIExp.toString());
}
}
private boolean checkGPSStatus() {
try {
locationManager = (LocationManager) EEmployeeApplication.getContext().getSystemService(Context.LOCATION_SERVICE);
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
return true;
} else {
return false;
}
} catch (Exception chkGPSExpt) {
Log.d("eEmp/chkGPS", " Exception Raised due to " + chkGPSExpt.toString());
return false;
}
}
#Override
protected void onDestroy() {
Log.d("eEmp/Launching", "onDestroy Called");
super.onDestroy();
}
#Override
public void onTaskStateChange(EmpConstants.TaskState State, String Msg, EEmployeeHTTPResponse result) {
switch (State){
case RequestStarted:
break;
case ResponseRecvd:
break;
case ResponseProcessing:
break;
case ResponseProcessed:
if (result != null) {
if (result.HTTPStatusCode == 200) {
if (result.Data != null) {
APP_VERSION_RESPONSE aResponse = (APP_VERSION_RESPONSE) result.Data.ActionResult;
if (aResponse!= null){
if (aResponse.APP_VER.equals(BuildConfig.VERSION_NAME)){
try{
System.out.print("Yes");
}catch (Exception e){
Log.d("/eEmp","/Excp due to"+e.toString());
}
}
}
}
}
}
}
}
}
In my android app, I am asking for permissions at launching of application.
Actually What I want is after launching application, it should ask for permissions and take user input whether accepted or denied then only should move to login page.
But after launching, it is asked for permissions and it is not waiting for user input means permissions dialog is opening and after 5 to 10 seconds login page is opening even though user not responding to permissions dialog.
Why it is happening like this?
Any help would be appreciated.
Your assumption that the android framework should take care of the permission handling process and should hold on to loading the UI components until the user has interacted with the permission is wrong. You need to handle to permission interaction with the user yourself.
Here's how your flow should be :
Ask the user for permission.
Wait for the user to interact with the dialog box.
Read the interaction response and evaluate if the permission was granted.
If the permission was granted, load the UI components.
In other words, you need to make sure that you hold on to doing anything that requires the permissions until the permissions are actually there.

External Sd-Card Stroage

I am new to android, I tried a lot codes, but can't get the path.
but using below code, I got the path of the External Sdcard, but could'nt access the External Sdcard directory.
public static List<StorageInfo> getStorageList() {
List<StorageInfo> list = new ArrayList<StorageInfo>();
String def_path = Environment.getExternalStorageDirectory().getPath();
boolean def_path_internal = !Environment.isExternalStorageRemovable();
String def_path_state = Environment.getExternalStorageState();
boolean def_path_available = def_path_state.equals(Environment.MEDIA_MOUNTED)
|| def_path_state.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
boolean def_path_readonly = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY);
BufferedReader buf_reader = null;
try {
HashSet<String> paths = new HashSet<String>();
buf_reader = new BufferedReader(new FileReader("/proc/mounts"));
String line;
int cur_display_number = 1;
while ((line = buf_reader.readLine()) != null) { if (line.contains("vfat") || line.contains("/mnt")) {
StringTokenizer tokens = new StringTokenizer(line, " ");
String unused = tokens.nextToken(); //device
String mount_point = tokens.nextToken(); //mount point
if (paths.contains(mount_point)) {
continue;
}
unused = tokens.nextToken(); //file system
List<String> flags = Arrays.asList(tokens.nextToken().split(",")); //flags
boolean readonly = flags.contains("ro");
if (mount_point.equals(def_path)) {
paths.add(def_path);
list.add(0, new StorageInfo(def_path, def_path_internal, readonly, -1));
} else if (line.contains("/dev/block/vold")) {
if (!line.contains("/mnt/secure")
&& !line.contains("/mnt/asec")
&& !line.contains("/mnt/obb")
&& !line.contains("/dev/mapper")
&& !line.contains("tmpfs")) {
paths.add(mount_point);
list.add(new StorageInfo(mount_point, false, readonly, cur_display_number++));
}
}
}
}
if (!paths.contains(def_path) && def_path_available) {
list.add(0, new StorageInfo(def_path, def_path_internal, def_path_readonly, -1));
}
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (buf_reader != null) {
try {
buf_reader.close();
} catch (IOException ex) {} }
}
return list;
}
How can i access the Sd card directory.
From android 23+ you need to gain user permission to write to the phones external storage. Do this by adding the following to your manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
If this does not give you access to the SD card then you may need to ask for permission at runtime before trying to access the card. Here is an example:
public void checkPermissions() {
String[] tmp = {"WRITE_EXTERNAL_STORAGE"};
for (String s : tmp) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!hasPermissionInManifest(getBaseContext(), s)) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
}
}
}
}
You need permissions to access other sensors in the phone and camera which can be done in a similar way. You can get the path to the external storage like this:
Environment.getExternalStorageDirectory().toString();

Download to external storage using downloadManager doesn't work properly on Galaxy S7

Downloading to internal storage works.
However, when I try to download to the external sdcard, then status doesn't update until after 2~3 minutes. (Meaning I get 0 bytes downloaded from cursor.getLong(cursor
.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));).
It eventually downloads after 2~3 minutes.
The notification status also says 0%
private void addToDownloadManager(String sourcePath, String destFolder, String deskFileName, DownloadManager downloadManager) {
try {
if(sourcePath == null || sourcePath.equals(""))
return;
try {
File folder = new File(destFolder);
if (!folder.exists()) {
folder.mkdirs();
}
}catch (Exception e) {
}
Uri Download_Uri = Uri.parse(sourcePath);
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
request.setAllowedOverRoaming(false);
request.setTitle("title");
request.setDescription("description");
File destination = new File(destFolder, deskFileName);
request.setDestinationUri(Uri.fromFile(destination));
downloadReference = downloadManager.enqueue(request);
} catch (Exception e) {
}
}
private Timer mDownloadStatusTimer;
public void downloadStatusTimerSchedule() {
if (mDownloadStatusTimer != null)
downloadStatusTimerCancel();
try {
mDownloadStatusTimer = new Timer("DownloadStatusTimer");
DownloadStatusTimer timer = new DownloadStatusTimer();
mDownloadStatusTimer.schedule(timer, 500, 500); // 0.5 second
} catch (Exception e) {
}
}
public void downloadStatusTimerCancel() {
if (mDownloadStatusTimer != null) {
mDownloadStatusTimer.cancel();
mDownloadStatusTimer.purge();
mDownloadStatusTimer = null;
}
}
private long bytes_downloaded = 0;
private long bytes_total = 0;
public class DownloadStatusTimer extends TimerTask {
#Override
public void run() {
if (mDownloadManager != null) {
DownloadManager.Query myDownloadQuery = new DownloadManager.Query();
Cursor cursor = mDownloadManager.query(myDownloadQuery);
bytes_downloaded = 0;
bytes_total = 0;
try {
if (cursor != null && cursor.moveToFirst()) {
try {
// Get downloaded size/total size
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL ||
cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_FAILED) {
// do nothing
} else {
bytes_downloaded += cursor.getLong(cursor
.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
bytes_total += cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
}
} catch (Exception e) {
}
while (cursor != null && cursor.moveToNext()) {
try {
// Get downloaded size/total size
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL ||
cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_FAILED) {
// do nothing
} else {
bytes_downloaded += cursor.getLong(cursor
.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
bytes_total += cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
}
} catch (Exception e) {
}
}
} else {
}
} catch (Exception e) {
} finally {
if (cursor != null) {
cursor.close();
}
}
Log.e("test", "Download size: " + bytes_downloaded + " / " + bytes_total);
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
try {
tv_download_status.setText("Download size: " + bytes_downloaded + " / " + bytes_total);
} catch (Exception e) {
}
}
});
}
}
}
I tested Note 4 and Galaxy S5 and they seems to be fine.
Could it be Android 6.0 thing? or S7?
Is it a bug? Or is there anything I am doing wrong here?
If you want to test it yourself, here's the project with source code:
https://drive.google.com/open?id=0BygTefPD845LTkp5QU1mOHRkMDQ
Here's APK to test:
https://drive.google.com/open?id=0By...Ec1ZHk5ZWRkWWc
[Edit]
My destination location is: /storage/806E-1A11/Android/data/com.joshua.externalsddownloadtest/files/download/video.mp4
Source is: http://downloads.4ksamples.com/downloads/[2160p]%204K-HD.Club-2013-Taipei%20101%20Fireworks%20Trailer%20(4ksamples.com).mp4
(I got the URL from the Mp4 Sample website)
File[] files = ContextCompat.getExternalFilesDirs(MainActivity.this, null);
destFolder = null;
for(int i=0; i< files.length; i++) {
if (!files[i].getAbsolutePath().equals(MainActivity.this.getExternalFilesDir(null).getPath())) {
destFolder = files[i].getAbsolutePath();
break;
}
}
boolean bDownloadToExternal = false;
if(destFolder == null) {
tv_download_destination.setText("No external storage found");
} else {
destFolder += "/download/";
tv_download_destination.setText("Destination location: " + destFolder + fileName);
bDownloadToExternal = true;
}
I think its about new permission system at android 6.
You should ask permissions in runtime like:
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != getPackageManager().PERMISSION_GRANTED){
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, YOUR_CONST_REQUEST_CODE);
}
}
And implement listener
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case YOUR_CONST_REQUEST_CODE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// invoke your download method
} else {
// if permissions was not granted
}
}
}
}
Other way you can set targetSdkVersion less then 23 in gradle file.
More about new permission system you can read here Android.com

Chromecast - SIGN_IN_REQUIRED

Only a small portion of my users are getting this error and I can't for the life of me figure it out. I use GooglePlayServicesUtil.isGooglePlayServicesAvailable(downloadService) to test whether or not Play Services is available, and it always returns SUCCESS. I setup the channel to connect to the Chromecast, and everything works fine up until the point where I try to use RemoteMediaPlayer.load. The result is always SIGN_IN_REQUIRED for some users, with resolution: null. The status.toString() is Failed to load: Status{statusCode=SIGN_IN_REQUIRED, resolution=null}. I'm really not sure what I am supposed to with this or how to get rid of the error for my few users who are getting this.
I don't know what portion is related, so I am just posting my entire controller class:
public class ChromeCastController extends RemoteController {
private static final String TAG = ChromeCastController.class.getSimpleName();
private CastDevice castDevice;
private GoogleApiClient apiClient;
private ConnectionCallbacks connectionCallbacks;
private ConnectionFailedListener connectionFailedListener;
private Cast.Listener castClientListener;
private boolean applicationStarted = false;
private boolean waitingForReconnect = false;
private boolean error = false;
private boolean ignoreNextPaused = false;
private String sessionId;
private FileProxy proxy;
private String rootLocation;
private RemoteMediaPlayer mediaPlayer;
private double gain = 0.5;
public ChromeCastController(DownloadService downloadService, CastDevice castDevice) {
this.downloadService = downloadService;
this.castDevice = castDevice;
SharedPreferences prefs = Util.getPreferences(downloadService);
rootLocation = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
}
#Override
public void create(boolean playing, int seconds) {
downloadService.setPlayerState(PlayerState.PREPARING);
connectionCallbacks = new ConnectionCallbacks(playing, seconds);
connectionFailedListener = new ConnectionFailedListener();
castClientListener = new Cast.Listener() {
#Override
public void onApplicationStatusChanged() {
if (apiClient != null && apiClient.isConnected()) {
Log.i(TAG, "onApplicationStatusChanged: " + Cast.CastApi.getApplicationStatus(apiClient));
}
}
#Override
public void onVolumeChanged() {
if (apiClient != null && applicationStarted) {
try {
gain = Cast.CastApi.getVolume(apiClient);
} catch(Exception e) {
Log.w(TAG, "Failed to get volume");
}
}
}
#Override
public void onApplicationDisconnected(int errorCode) {
shutdownInternal();
}
};
Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions.builder(castDevice, castClientListener);
apiClient = new GoogleApiClient.Builder(downloadService)
.addApi(Cast.API, apiOptionsBuilder.build())
.addConnectionCallbacks(connectionCallbacks)
.addOnConnectionFailedListener(connectionFailedListener)
.build();
apiClient.connect();
}
#Override
public void start() {
if(error) {
error = false;
Log.w(TAG, "Attempting to restart song");
startSong(downloadService.getCurrentPlaying(), true, 0);
return;
}
try {
mediaPlayer.play(apiClient);
} catch(Exception e) {
Log.e(TAG, "Failed to start");
}
}
#Override
public void stop() {
try {
mediaPlayer.pause(apiClient);
} catch(Exception e) {
Log.e(TAG, "Failed to pause");
}
}
#Override
public void shutdown() {
try {
if(mediaPlayer != null && !error) {
mediaPlayer.stop(apiClient);
}
} catch(Exception e) {
Log.e(TAG, "Failed to stop mediaPlayer", e);
}
try {
if(apiClient != null) {
Cast.CastApi.stopApplication(apiClient);
Cast.CastApi.removeMessageReceivedCallbacks(apiClient, mediaPlayer.getNamespace());
mediaPlayer = null;
applicationStarted = false;
}
} catch(Exception e) {
Log.e(TAG, "Failed to shutdown application", e);
}
if(apiClient != null && apiClient.isConnected()) {
apiClient.disconnect();
}
apiClient = null;
if(proxy != null) {
proxy.stop();
proxy = null;
}
}
private void shutdownInternal() {
// This will call this.shutdown() indirectly
downloadService.setRemoteEnabled(RemoteControlState.LOCAL, null);
}
#Override
public void updatePlaylist() {
if(downloadService.getCurrentPlaying() == null) {
startSong(null, false, 0);
}
}
#Override
public void changePosition(int seconds) {
try {
mediaPlayer.seek(apiClient, seconds * 1000L);
} catch(Exception e) {
Log.e(TAG, "FAiled to seek to " + seconds);
}
}
#Override
public void changeTrack(int index, DownloadFile song) {
startSong(song, true, 0);
}
#Override
public void setVolume(boolean up) {
double delta = up ? 0.1 : -0.1;
gain += delta;
gain = Math.max(gain, 0.0);
gain = Math.min(gain, 1.0);
getVolumeToast().setVolume((float) gain);
try {
Cast.CastApi.setVolume(apiClient, gain);
} catch(Exception e) {
Log.e(TAG, "Failed to the volume");
}
}
#Override
public int getRemotePosition() {
if(mediaPlayer != null) {
return (int) (mediaPlayer.getApproximateStreamPosition() / 1000L);
} else {
return 0;
}
}
#Override
public int getRemoteDuration() {
if(mediaPlayer != null) {
return (int) (mediaPlayer.getStreamDuration() / 1000L);
} else {
return 0;
}
}
void startSong(DownloadFile currentPlaying, boolean autoStart, int position) {
if(currentPlaying == null) {
try {
if (mediaPlayer != null && !error) {
mediaPlayer.stop(apiClient);
}
} catch(Exception e) {
// Just means it didn't need to be stopped
}
downloadService.setPlayerState(PlayerState.IDLE);
return;
}
downloadService.setPlayerState(PlayerState.PREPARING);
MusicDirectory.Entry song = currentPlaying.getSong();
try {
MusicService musicService = MusicServiceFactory.getMusicService(downloadService);
String url;
// Offline, use file proxy
if(Util.isOffline(downloadService) || song.getId().indexOf(rootLocation) != -1) {
if(proxy == null) {
proxy = new FileProxy(downloadService);
proxy.start();
}
url = proxy.getPublicAddress(song.getId());
} else {
if(proxy != null) {
proxy.stop();
proxy = null;
}
if(song.isVideo()) {
url = musicService.getHlsUrl(song.getId(), currentPlaying.getBitRate(), downloadService);
} else {
url = musicService.getMusicUrl(downloadService, song, currentPlaying.getBitRate());
}
url = fixURLs(url);
}
// Setup song/video information
MediaMetadata meta = new MediaMetadata(song.isVideo() ? MediaMetadata.MEDIA_TYPE_MOVIE : MediaMetadata.MEDIA_TYPE_MUSIC_TRACK);
meta.putString(MediaMetadata.KEY_TITLE, song.getTitle());
if(song.getTrack() != null) {
meta.putInt(MediaMetadata.KEY_TRACK_NUMBER, song.getTrack());
}
if(!song.isVideo()) {
meta.putString(MediaMetadata.KEY_ARTIST, song.getArtist());
meta.putString(MediaMetadata.KEY_ALBUM_ARTIST, song.getArtist());
meta.putString(MediaMetadata.KEY_ALBUM_TITLE, song.getAlbum());
String coverArt = "";
if(proxy == null) {
coverArt = musicService.getCoverArtUrl(downloadService, song);
coverArt = fixURLs(coverArt);
meta.addImage(new WebImage(Uri.parse(coverArt)));
} else {
File coverArtFile = FileUtil.getAlbumArtFile(downloadService, song);
if(coverArtFile != null && coverArtFile.exists()) {
coverArt = proxy.getPublicAddress(coverArtFile.getPath());
meta.addImage(new WebImage(Uri.parse(coverArt)));
}
}
}
String contentType;
if(song.isVideo()) {
contentType = "application/x-mpegURL";
}
else if(song.getTranscodedContentType() != null) {
contentType = song.getTranscodedContentType();
} else if(song.getContentType() != null) {
contentType = song.getContentType();
} else {
contentType = "audio/mpeg";
}
// Load it into a MediaInfo wrapper
MediaInfo mediaInfo = new MediaInfo.Builder(url)
.setContentType(contentType)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setMetadata(meta)
.build();
if(autoStart) {
ignoreNextPaused = true;
}
mediaPlayer.load(apiClient, mediaInfo, autoStart, position * 1000L).setResultCallback(new ResultCallback<RemoteMediaPlayer.MediaChannelResult>() {
#Override
public void onResult(RemoteMediaPlayer.MediaChannelResult result) {
if (result.getStatus().isSuccess()) {
// Handled in other handler
} else if(result.getStatus().getStatusCode() != ConnectionResult.SIGN_IN_REQUIRED) {
Log.e(TAG, "Failed to load: " + result.getStatus().toString());
failedLoad();
}
}
});
} catch (IllegalStateException e) {
Log.e(TAG, "Problem occurred with media during loading", e);
failedLoad();
} catch (Exception e) {
Log.e(TAG, "Problem opening media during loading", e);
failedLoad();
}
}
private String fixURLs(String url) {
// Only change to internal when using https
if(url.indexOf("https") != -1) {
SharedPreferences prefs = Util.getPreferences(downloadService);
int instance = prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
String externalUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null);
String internalUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_INTERNAL_URL + instance, null);
url = url.replace(internalUrl, externalUrl);
}
// Use separate profile for Chromecast so users can do ogg on phone, mp3 for CC
return url.replace(Constants.REST_CLIENT_ID, Constants.CHROMECAST_CLIENT_ID);
}
private void failedLoad() {
Util.toast(downloadService, downloadService.getResources().getString(R.string.download_failed_to_load));
downloadService.setPlayerState(PlayerState.STOPPED);
error = true;
}
private class ConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks {
private boolean isPlaying;
private int position;
private ResultCallback<Cast.ApplicationConnectionResult> resultCallback;
ConnectionCallbacks(boolean isPlaying, int position) {
this.isPlaying = isPlaying;
this.position = position;
resultCallback = new ResultCallback<Cast.ApplicationConnectionResult>() {
#Override
public void onResult(Cast.ApplicationConnectionResult result) {
Status status = result.getStatus();
if (status.isSuccess()) {
ApplicationMetadata applicationMetadata = result.getApplicationMetadata();
sessionId = result.getSessionId();
String applicationStatus = result.getApplicationStatus();
boolean wasLaunched = result.getWasLaunched();
applicationStarted = true;
setupChannel();
} else {
shutdownInternal();
}
}
};
}
#Override
public void onConnected(Bundle connectionHint) {
if (waitingForReconnect) {
Log.i(TAG, "Reconnecting");
reconnectApplication();
} else {
launchApplication();
}
}
#Override
public void onConnectionSuspended(int cause) {
Log.w(TAG, "Connection suspended");
isPlaying = downloadService.getPlayerState() == PlayerState.STARTED;
position = getRemotePosition();
waitingForReconnect = true;
}
void launchApplication() {
try {
Cast.CastApi.launchApplication(apiClient, CastCompat.APPLICATION_ID, false).setResultCallback(resultCallback);
} catch (Exception e) {
Log.e(TAG, "Failed to launch application", e);
}
}
void reconnectApplication() {
try {
Cast.CastApi.joinApplication(apiClient, CastCompat.APPLICATION_ID, sessionId).setResultCallback(resultCallback);
} catch (Exception e) {
Log.e(TAG, "Failed to reconnect application", e);
}
}
void setupChannel() {
if(!waitingForReconnect) {
mediaPlayer = new RemoteMediaPlayer();
mediaPlayer.setOnStatusUpdatedListener(new RemoteMediaPlayer.OnStatusUpdatedListener() {
#Override
public void onStatusUpdated() {
MediaStatus mediaStatus = mediaPlayer.getMediaStatus();
if (mediaStatus == null) {
return;
}
switch (mediaStatus.getPlayerState()) {
case MediaStatus.PLAYER_STATE_PLAYING:
if (ignoreNextPaused) {
ignoreNextPaused = false;
}
downloadService.setPlayerState(PlayerState.STARTED);
break;
case MediaStatus.PLAYER_STATE_PAUSED:
if (!ignoreNextPaused) {
downloadService.setPlayerState(PlayerState.PAUSED);
}
break;
case MediaStatus.PLAYER_STATE_BUFFERING:
downloadService.setPlayerState(PlayerState.PREPARING);
break;
case MediaStatus.PLAYER_STATE_IDLE:
if (mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_FINISHED) {
downloadService.setPlayerState(PlayerState.COMPLETED);
downloadService.onSongCompleted();
} else if (mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_INTERRUPTED) {
if (downloadService.getPlayerState() != PlayerState.PREPARING) {
downloadService.setPlayerState(PlayerState.PREPARING);
}
} else if (mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_ERROR) {
Log.e(TAG, "Idle due to unknown error");
downloadService.setPlayerState(PlayerState.COMPLETED);
downloadService.next();
} else {
Log.w(TAG, "Idle reason: " + mediaStatus.getIdleReason());
downloadService.setPlayerState(PlayerState.IDLE);
}
break;
}
}
});
}
try {
Cast.CastApi.setMessageReceivedCallbacks(apiClient, mediaPlayer.getNamespace(), mediaPlayer);
} catch (IOException e) {
Log.e(TAG, "Exception while creating channel", e);
}
if(!waitingForReconnect) {
DownloadFile currentPlaying = downloadService.getCurrentPlaying();
startSong(currentPlaying, isPlaying, position);
}
if(waitingForReconnect) {
waitingForReconnect = false;
}
}
}
private class ConnectionFailedListener implements GoogleApiClient.OnConnectionFailedListener {
#Override
public void onConnectionFailed(ConnectionResult result) {
shutdownInternal();
}
}
}
Edit for logs:
03-28 19:04:49.757 6305-6305/github.daneren2005.dsub I/ChromeCastController﹕ onApplicationStatusChanged: Chromecast Home Screen
03-28 19:04:52.280 6305-6305/github.daneren2005.dsub I/ChromeCastController﹕ onApplicationStatusChanged: null
03-28 19:04:54.162 6305-6305/github.daneren2005.dsub I/ChromeCastController﹕ onApplicationStatusChanged: Ready To Cast
03-28 19:05:05.194 6305-6305/github.daneren2005.dsub E/ChromeCastController﹕ Failed to load: Status{statusCode=SIGN_IN_REQUIRED, resolution=null}
It is strange that you are getting such status code at that time. What comes to mind is that the user may have not logged into his/her gmail account or something along those lines. Do you have the log file for us to take a look at to see if we can get more from the context? Also, to be sure, such user sees the application launched on the TV and only when it comes to loading a media that error is thrown?
The issue is due to using a Self Signed Certificate. I didn't realize the issue on my old phone because I had changed hosts and bought a normal certificate after switching phones. It would be nice if the SDK would through a useful error though. The one thrown makes you think that it is a problem with connecting to the Play Services SDK, and not a problem with the actual URL being used.

Handling the case when you have missed a turn in Google Maps

I am working on an Android navigation application for blind people. So naturally no use of displaying map on the screen. My code for now gets the path by building an url and then parsing the html document. I want to make this live i.e. i want to handle the case when he/she goes off the path or goes in the wrong direction, i want my app to alert him.
Is such a thing possible using a Google Maps feature? If possible please give details about that feature or if no such feature exists then is it possible to use existing feature and use it in some way to help solve the problem.
This is my present code:
public class GPSTracking extends Activity implements
TextToSpeech.OnInitListener
{
protected static final int RESULT_SPEECH_start = 1;
protected static final int RESULT_SPEECH_end = 2;
protected static final int RESTART_ALL = 3;
//total distance travelled till last turn
Float totalDistance;
//distance to be travelled from present point to the next point
Float obtainedDistance;
//upper button
Button btnShowLocation;
//bottom button
Button btnShowLocationNo;
//to narate what user should do.
TextToSpeech tts;
//used to get name of current location
Geocoder geocoder;
//used to find positioning feature
GPS gps;
//start and position of the journey
String startPosition=null, endPosition=null;
//strings containing the path.
String[] string = null;
//vibrate the mobile
Vibrator viberator;
//indexing the present value of string which contains the path
int i = 0;
//to maintain proper order of events
int steps=0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//button on top
btnShowLocation = (Button) findViewById(R.id.trueButton);
//button on the lower side
btnShowLocationNo = (Button) findViewById(R.id.falseButton);
//initialising the text to speech
tts = new TextToSpeech(this, this);
//initialising the vibrator.
viberator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
//to know what the current location
btnShowLocation.setOnClickListener(new View.OnClickListener() {
//to avoid start of multiple threads
boolean mytaskStarted=false;
String str=null;
#Override
public void onClick(View v) {
if(steps==0){
//to make sure values are reset
totalDistance=(float)0;
obtainedDistance=(float)0;
mytaskStarted=false;
string=null;
str=null;
i=0;
//only ask for initial position if not set
if(startPosition == null){
speakOut("Please enter the start position");
//takes the input using speech to text
intentGenerator(RESULT_SPEECH_start);
}
else{
//to enter the destination
speakOut("press the button again");
steps=1;
}
}
else if(steps==1){
//to enter the destination
speakOut("Please enter the destination");
intentGenerator(RESULT_SPEECH_end);
}
else if(steps==2){
//for a impatient user
speakOut("please wait");
//to avoid start of many asynchronous task
if(!mytaskStarted){
mytaskStarted=true;
//asynchronous task to find the path to be followed
new GetPath().execute();
}
}
else if(steps==3){
if (string != null && i < string.length) {
if(gps!=null && gps.isGpsEnabled()){
speakOut(i + 1 + " " + string[i]);
if(i>0 && i<string.length-1 && (string[i]+" ").lastIndexOf(" m ")>-1){
str=(string[i]+" ").substring(0,(string[i]+" ").lastIndexOf(" m ")+3);
obtainedDistance=Float.parseFloat(str.substring(1+str.substring(0,str.substring(0,str.lastIndexOf(" ")).lastIndexOf(" ")).lastIndexOf(" "),str.substring(0,str.lastIndexOf(" ")).lastIndexOf(" ")));
//increment only when present distance greater than distance in present string so that one will know when to turn.
if(((totalDistance+obtainedDistance)-gps.getApprximateDistance())<10)
{
i++;
totalDistance=totalDistance+obtainedDistance;
}
}
else if(i>0 && i<string.length-1 && (string[i]+" ").lastIndexOf(" km ")>-1){
str=(string[i]+" ").substring(0,(string[i]+" ").lastIndexOf(" km ")+4);
obtainedDistance=Float.parseFloat(str.substring(1+str.substring(0,str.substring(0,str.lastIndexOf(" ")).lastIndexOf(" ")).lastIndexOf(" "),str.substring(0,str.lastIndexOf(" ")).lastIndexOf(" ")));
obtainedDistance*=1000;
//increment only when present distance greater than distance in present string so that one will know when to turn.
if(((totalDistance+obtainedDistance)-gps.getApprximateDistance())<10)
{
i++;
totalDistance=totalDistance+obtainedDistance;
}
}
else if(i==0 ){
i++;
}
}
else if(gps!=null){
gps.resetDistance();
gps.stopUsingGPS();
//if gps not working.
speakOut(i + 1 + " " + string[i]);
i++;
}
else{
speakOut(i + 1 + " " + string[i]);
i++;
}
} else if (string != null && i >= string.length) {
i = 0;
}
}
}
});
//to get present location
btnShowLocation.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
if(gps==null){
gps = new GPS(AndroidGPSTrackingActivity.this);
}
if (gps.canGetLocation()) {
double longitude = gps.getLongitude();
double latitude = gps.getLatitude();
Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
try {
//obtain the address of present location
List<Address> listAddresses = geocoder.getFromLocation(latitude, longitude, 1);
if(null!=listAddresses&&listAddresses.size()>0){
if (listAddresses.size() > 0) {
StringBuilder result = new StringBuilder();
for(int i = 0; i < listAddresses.size(); i++){
Address address = listAddresses.get(i);
int maxIndex = address.getMaxAddressLineIndex();
for (int x = 0; x <= maxIndex; x++ ){
if(address.getAddressLine(x)!=null){
result.append(address.getAddressLine(x));
result.append(",");
}
}
if(address.getLocality()!=null){
result.append(address.getLocality());
result.append("\n\n");
}
}
//if position accurate
if(gps.isGpsEnabled()){
speakOut(result.toString()+" is Your current location");
startPosition=result.toString();
Toast.makeText(
getApplicationContext(),startPosition,
Toast.LENGTH_LONG).show();
} else if(gps.isNetworkEnabled()){
speakOut(result.toString()+" is Your current approximate location. You have to give input of your present location on your own.");
Toast.makeText(
getApplicationContext(),result.toString(),
Toast.LENGTH_LONG).show();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
gps.showSettingsAlert();
startPosition=null;
speakOut(" please turn on gps");
}
return false;
}
});
//to know what the previous direction string
btnShowLocationNo.setOnClickListener(new View.OnClickListener() {
int j=0;
#Override
public void onClick(View arg0) {
if(string!=null && j<string.length){
speakOut(j + 1 + " " + string[j]);
j++;
}
else if(string!=null && j>=string.length){
j=0;
}
}
});
//to reset all values for fresh start
btnShowLocationNo.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
speakOut("Values reset");
steps=0;
string=null;
i=0;
startPosition=null;
gps.stopUsingGPS();
gps=null;
endPosition=null;
return false;
}
});
}
//function to handle he text obtained from speech to text.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
//set the start
case RESULT_SPEECH_start:
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> text = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
Toast.makeText(getApplicationContext(), text.get(0),
Toast.LENGTH_SHORT).show();
startPosition = text.get(0);
steps=1;
//speakOut("please press button again");
}
else{
steps=0;
}
break;
//to set the end
case RESULT_SPEECH_end:
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> text = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
Toast.makeText(getApplicationContext(), text.get(0),
Toast.LENGTH_SHORT).show();
endPosition = text.get(0);
steps=2;
}
else{
steps=1;
}
break;
}
}
//function to generate intent to take speech input
public void intentGenerator(int code) {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US");
try {
startActivityForResult(intent, code);
} catch (ActivityNotFoundException a) {
Toast.makeText(getApplicationContext(),
"Opps! Your device doesn't support Speech to Text",
Toast.LENGTH_SHORT).show();
speakOut("Opps! Your device doesn't support Speech to Text");
}
}
//mobile gives instruction.
private void speakOut(String text) {
tts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
while (tts.isSpeaking()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//asynchronous task to get the path. THIS IS USED TO AVOID OVERLOAD THE MAIN THRED AND AVOID FORCE CLOSE OF THE APPLICATION
private class GetPath extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
string=null;
String html="";
//forming url
URL net = new URL(("http://maps.google.com/maps?saddr="+startPosition+" &daddr= "+endPosition).replaceAll(" ","%20"));
URLConnection netConnection = null;
netConnection = net.openConnection();
//to take the input from google maps
BufferedReader in = null;
in = new BufferedReader(new InputStreamReader(netConnection.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
html+=inputLine;
}
//jsoup parser to parse the document obtained from google maps
Document doc = Jsoup.parse(html);
//obtain necessary part of the document
Elements el = doc.getElementsByClass("dir-mrgnr");
//to remove html tags
String str = el.text();
str = str.replaceAll("[0-9]+[.] ", "\n");
string = str.split("\n");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
//so that on press of button again mobile can read the directions to users
steps=3;
}
}
#Override
public void onDestroy() {
//shutdown
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
#Override
protected void onStart() {
gps = new GPS(AndroidGPSTrackingActivity.this);
super.onStart();
}
#Override
protected void onStop() {
if (tts != null) {
tts.stop();
tts.shutdown();
}
if(gps!=null){
gps.stopUsingGPS();
}
super.onStop();
}
#Override
public void onInit(int status) {
//initialising the text to speech
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.US);
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "Language is not supported");
} else {
btnShowLocation.setEnabled(true);
}
} else {
Log.e("TTS", "Initilization Failed");
}
}
}

Categories

Resources