I am getting this error when I run the app on any pre lollipop device, unless the app is running perfectly in >= 5.0 versions.
This is what I am getting:
Process: com.hashrail.newyorkcityguide, PID: 31045
java.lang.NullPointerException: IBitmapDescriptorFactory is not initialized
at com.google.android.gms.common.internal.zzx.zzb(Unknown Source)
at com.google.android.gms.maps.model.BitmapDescriptorFactory.zzAi(Unknown Source)
at com.google.android.gms.maps.model.BitmapDescriptorFactory.fromBitmap(Unknown Source)
at com.hashrail.newyorkcityguide.fragment.FragmentNearby.onActivityCreated(FragmentNearby.java:160)
at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1983)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1092)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
at com.hashrail.newyorkcityguide.MainActivity.showScreen(MainActivity.java:335)
at com.hashrail.newyorkcityguide.MainActivity.showNearbyFragment(MainActivity.java:249)
at com.hashrail.newyorkcityguide.fragment.FragmentListPlaces$OnMapClickListener$1.run(FragmentListPlaces.java:243)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5333)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
at dalvik.system.NativeStart.main(Native Method)
05-18 11:31:27.932 31045-31145/com.hashrail.newyorkcityguide E/GAv4: Successfully bound to service but never got onServiceConnected callback
MainActivity
public class MainActivity extends FragmentActivity{
public static float density;
private static final int PERMISSION_REQUEST_CODE_LOCATION = 1;
public static Context context;
private GPSTracker gps;
private double latitudeGet, longitudeGet;
public static String getApiKey() {
return context.getString(R.string.google_api_key);
}
private String cityGet, countryGet;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MapsInitializer.initialize(getApplicationContext());
try {
context = this;
ThemeUtil.setTranslucentTheme(this);
density = getResources().getDisplayMetrics().density;
setContentView(R.layout.activity_main);
/* if (android.os.Build.VERSION.SDK_INT > 9 || android.os.Build.VERSION.SDK_INT < 21 ) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}*/
DatabaseManager.initWithContext(this);
ImageLoader.getInstance().init(
ImageOptionsBuilder.createImageLoaderConfiguration(this));
Constants.DEFAULT_PHOTO_WIDTH = getResources().getDisplayMetrics().widthPixels;
showHomeFragment();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
NearbyPlacesManager.getInstance();
}
}, 1000);
new AboutDataLoader().loadData(this);
if (checkPermission(Manifest.permission.ACCESS_FINE_LOCATION,getApplicationContext(),MainActivity.this)) {
getCurrentArea();
}
else
{
requestPermission(Manifest.permission.ACCESS_FINE_LOCATION,PERMISSION_REQUEST_CODE_LOCATION,getApplicationContext(),MainActivity.this);
}
// initAdmob();
initAppoDeal();
/* if (NetConnectivity.isOnline(getApplicationContext())) {
} else {
}*/
//Fabric.with(this, new Crashlytics());
} catch (Exception e) {
e.printStackTrace();
}
}
private void initAppoDeal() {
String appKey = "703f62f01e41eecc435236577c2e5500d1f291d2acd9fab3";
Appodeal.initialize(this, appKey, Appodeal.BANNER);
Appodeal.show(this, Appodeal.BANNER);
/*
Appodeal.setNativeCallbacks(new NativeCallbacks() {
#Override
public void onNativeLoaded(List<NativeAd> nativeAds) {
Log.d("Appodeal", "onNativeLoaded");
}
#Override
public void onNativeFailedToLoad() {
Log.d("Appodeal", "onNativeFailedToLoad");
}
#Override
public void onNativeShown(NativeAd nativeAd) {
Log.d("Appodeal", "onNativeShown");
}
#Override
public void onNativeClicked(NativeAd nativeAd) {
Log.d("Appodeal", "onNativeClicked");
Toast.makeText(MainActivity.this, "Your Clicked", Toast.LENGTH_LONG).show();
}
});*/
}
public static void requestPermission(String strPermission,int perCode,Context _c,Activity _a){
if (ActivityCompat.shouldShowRequestPermissionRationale(_a,strPermission)){
//Toast.makeText(getApplicationContext(),"GPS permission allows us to access location data. Please allow in App Settings for additional functionality.",Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(_a,new String[]{strPermission},perCode);
}
}
public static boolean checkPermission(String strPermission,Context _c,Activity _a){
int result = ContextCompat.checkSelfPermission(_c, strPermission);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE_LOCATION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getCurrentArea();
} else {
Toast.makeText(getApplicationContext(),"Permission Denied, You cannot access location data.",Toast.LENGTH_LONG).show();
}
break;
}
}
private void getCurrentArea() {
gps = new GPSTracker(MainActivity.this);
// check if GPS enabled
if (gps.canGetLocation()) {
latitudeGet = gps.getLatitude();
longitudeGet = gps.getLongitude();
Geocoder geoCoder = new Geocoder(getBaseContext(), Locale.getDefault());
try {
List<Address> addresses = geoCoder.getFromLocation(latitudeGet, longitudeGet, 1);
//List<Address> addresses = geoCoder.getFromLocation(17.4126274,78.2679594, 1);
if (addresses.size() > 0) {
System.out.println(addresses.get(0).getLocality());
System.out.println(addresses.get(0).getCountryName());
cityGet = addresses.get(0).getLocality();
countryGet = addresses.get(0).getCountryName();
AppSettings.LATITUDE = latitudeGet;
AppSettings.LONGITUDE = longitudeGet;
// AppSettings.LATITUDE = 17.4126274;
// AppSettings.LONGITUDE= 78.2679594;
AppSettings.TOWN = cityGet;
AppSettings.COUNTRY = countryGet;
}
//showToastMessage(add);
// Toast.makeText(MainActivity.this, "Your Location is - " + cityGet + " " + countryGet, Toast.LENGTH_LONG).show();
} catch (IOException e1) {
e1.printStackTrace();
}
// \n is for new line
// Toast.makeText(MainActivity.this, "Your Location is - \nLat: " + latitudeGet + "\nLong: " + longitudeGet, Toast.LENGTH_LONG).show();
} else {
// can't get location
// GPS or Network is not enabled
// Ask user to enable GPS/network in settings
gps.showSettingsAlert();
}
}
public void showNearbyFragment(Constants.PLACE_TYPES type, Place placeDetail, boolean showCurrentLocation) {
showScreen(FragmentNearby.newInstance(type, placeDetail, showCurrentLocation), FragmentNearby.TAG, true, false);
}
public boolean isNearbyFragmentShowed() {
return getSupportFragmentManager().findFragmentByTag(FragmentNearby.TAG) != null;
}
public void showListFragment(Constants.PLACE_TYPES type) {
showScreen(FragmentListPlaces.newInstance(type), FragmentListPlaces.TAG, true, false);
}
private void showHomeFragment() {
showScreen(FragmentHome.newInstance(), FragmentHome.TAG, false, false);
}
public void showForecastFragment() {
showScreen(FragmentForecast.newInstance(), FragmentForecast.TAG, true, false);
}
public void showAboutFragment() {
showScreen(FragmentAbout.newInstance(), FragmentAbout.TAG, true, false);
}
public void showLoadingDialog() {
DialogFragmentLoading.newInstance().show(getSupportFragmentManager(), DialogFragmentLoading.TAG);
}
public void showPhotoDialog(Photo photo) {
DialogFragmentPhoto.newInstance(photo).show(getSupportFragmentManager(), DialogFragmentPhoto.TAG);
}
public void showPlaceDetailFragment(Place place, Constants.PLACE_TYPES type) {
FragmentPlaceDetail fragmentPlaceDetail = FragmentPlaceDetail.newInstance(place, type);
showScreen(fragmentPlaceDetail, FragmentPlaceDetail.TAG, true, false);
}
public void showReviewsScreen(PlaceDetails placeDetails, Constants.PLACE_TYPES type) {
FragmentReviews fragmentReviews = FragmentReviews.newInstance(placeDetails, type);
showScreen(fragmentReviews, FragmentReviews.TAG, true, false);
}
public void hideLoadingDialog() {
Fragment loadingFragment = getSupportFragmentManager().findFragmentByTag(DialogFragmentLoading.TAG);
if (loadingFragment != null) {
((DialogFragmentLoading) loadingFragment).dismiss();
}
}
private void showScreen(Fragment content,
String contentTag, boolean addToBackStack, boolean clearBackStack) {
if (!NetworkFetcher.isNetworkConnected(MainActivity.this) && !contentTag.equalsIgnoreCase(FragmentHome.TAG)) {
Toast.makeText(this, getString(R.string.no_internet_connection), Toast.LENGTH_LONG).show();
return;
}
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(R.anim.left_slide_in, R.anim.left_slide_out,
R.anim.right_slide_in, R.anim.right_slide_out);
ft.replace(R.id.activity_main_content, content, contentTag);
if (clearBackStack) {
fm.popBackStackImmediate(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
if (addToBackStack) {
ft.addToBackStack(String.valueOf(System.identityHashCode(content)));
}
ft.commitAllowingStateLoss();
fm.executePendingTransactions();
}
}
Related
I implemented the new autocomplete place sdk in an Android app but it does not show most of places for Nigeria. For example, when I enter spar PH it should show the location SPAR PH, Forces Avenue, Port Harcourt, Nigeria in the suggestion but doesn't. There are other examples that aren't working, too. This was working with the autocomplete Place API but not the new autocomplete .
activity code
public class LocationPickActivity extends BaseActivity
implements OnMapReadyCallback,
GoogleMap.OnCameraMoveListener,
GoogleMap.OnCameraIdleListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationPickIView {
private static final LatLngBounds BOUNDS_INDIA = new LatLngBounds(new LatLng(-0, 0), new LatLng(0, 0));
private Location mLastKnownLocation;
protected GoogleApiClient mGoogleApiClient;
#BindView(R.id.appbar)
AppBarLayout appbar;
#BindView(R.id.toolbar)
Toolbar toolbar;
#BindView(R.id.source)
EditText source;
#BindView(R.id.destination)
EditText destination;
#BindView(R.id.destination_layout)
LinearLayout destinationLayout;
#BindView(R.id.home_address_layout)
LinearLayout homeAddressLayout;
#BindView(R.id.work_address_layout)
LinearLayout workAddressLayout;
#BindView(R.id.home_address)
TextView homeAddress;
#BindView(R.id.work_address)
TextView workAddress;
#BindView(R.id.locations_rv)
RecyclerView locationsRv;
#BindView(R.id.location_bs_layout)
CardView locationBsLayout;
#BindView(R.id.dd)
CoordinatorLayout dd;
boolean isEnableIdle = false;
#BindView(R.id.llSource)
LinearLayout llSource;
private boolean isLocationRvClick = false;
private boolean isSettingLocationClick = false;
private boolean mLocationPermissionGranted;
private GoogleMap mGoogleMap;
private String s_address;
private Double s_latitude;
private Double s_longitude;
private FusedLocationProviderClient mFusedLocationProviderClient;
private BottomSheetBehavior mBottomSheetBehavior;
private Boolean isEditable = true;
private UserAddress home, work = null;
private LocationPickPresenter<LocationPickActivity> presenter = new LocationPickPresenter<>();
private EditText selectedEditText;
private PlacesAutoCompleteAdapter mAutoCompleteAdapter;
//Base on action we are show/hide view and setResults
private String actionName = Constants.LocationActions.SELECT_SOURCE;
PlacesClient placesClient =null;
private TextWatcher filterTextWatcher = new TextWatcher() {
public void afterTextChanged(Editable s) {
if (isEditable) if (!s.toString().equals("") && mGoogleApiClient.isConnected()) {
locationsRv.setVisibility(View.VISIBLE);
mAutoCompleteAdapter.getFilter().filter(s.toString());
if (mBottomSheetBehavior.getState() != BottomSheetBehavior.STATE_EXPANDED)
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
} else if (!mGoogleApiClient.isConnected()) Log.e("ERROR", "API_NOT_CONNECTED");
if (s.toString().equals("")) locationsRv.setVisibility(View.GONE);
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
#Override
public int getLayoutId() {
return R.layout.activity_location_pick;
}
#Override
public void initView() {
buildGoogleApiClient();
ButterKnife.bind(this);
presenter.attachView(this);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Places.initialize(getApplicationContext(), getString(R.string.google_map_key));
placesClient = Places.createClient(this);
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mBottomSheetBehavior = BottomSheetBehavior.from(locationBsLayout);
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
mAutoCompleteAdapter = new PlacesAutoCompleteAdapter(this, R.layout.list_item_location, mGoogleApiClient, BOUNDS_INDIA);
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
locationsRv.setLayoutManager(mLinearLayoutManager);
locationsRv.setAdapter(mAutoCompleteAdapter);
source.addTextChangedListener(filterTextWatcher);
destination.addTextChangedListener(filterTextWatcher);
source.setOnFocusChangeListener((view, hasFocus) -> {
if (hasFocus) selectedEditText = source;
});
destination.setOnFocusChangeListener((view, hasFocus) -> {
if (hasFocus) selectedEditText = destination;
});
destination.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_DONE) {
setResult(Activity.RESULT_OK, new Intent());
finish();
return true;
}
return false;
});
source.setText(MvpApplication.RIDE_REQUEST.containsKey(Constants.RIDE_REQUEST.SRC_ADD)
? TextUtils.isEmpty(Objects.requireNonNull(MvpApplication.RIDE_REQUEST.get(Constants.RIDE_REQUEST.SRC_ADD)).toString())
? ""
: String.valueOf(MvpApplication.RIDE_REQUEST.get(Constants.RIDE_REQUEST.SRC_ADD))
: "");
destination.setText(MvpApplication.RIDE_REQUEST.containsKey(Constants.RIDE_REQUEST.DEST_ADD)
? TextUtils.isEmpty(Objects.requireNonNull(MvpApplication.RIDE_REQUEST.get(Constants.RIDE_REQUEST.DEST_ADD)).toString())
? ""
: String.valueOf(MvpApplication.RIDE_REQUEST.get(Constants.RIDE_REQUEST.DEST_ADD))
: "");
locationsRv.addOnItemTouchListener(new RecyclerItemClickListener(this, (view, position) -> {
if (mAutoCompleteAdapter.getItemCount() == 0) return;
final PlacesAutoCompleteAdapter.PlaceAutocomplete item = mAutoCompleteAdapter.getItem(position);
final String placeId = String.valueOf(item.placeId);
Log.i("LocationPickActivity", "Autocomplete item selected: " + item.address);
List<Field> placeFields = Arrays.asList(Field.LAT_LNG);
);
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
actionName = bundle.getString("actionName",Constants.LocationActions.SELECT_SOURCE);
if (!TextUtils.isEmpty(actionName) && actionName.equalsIgnoreCase(Constants.LocationActions.SELECT_SOURCE)) {
destination.setCursorVisible(false);
source.setCursorVisible(true);
source.requestFocus();
selectedEditText = source;
}else if (!TextUtils.isEmpty(actionName) && actionName.equalsIgnoreCase(Constants.LocationActions.SELECT_DESTINATION)){
source.setCursorVisible(false);
destination.setCursorVisible(true);
destination.setText("");
destination.requestFocus();
selectedEditText = destination;
}else if (!TextUtils.isEmpty(actionName) && actionName.equals(Constants.LocationActions.CHANGE_DESTINATION)){
llSource.setVisibility(View.GONE);
source.setHint(getString(R.string.select_location));
selectedEditText = destination;
}else if (!TextUtils.isEmpty(actionName) && (actionName.equals(Constants.LocationActions.SELECT_HOME)|| actionName.equals(Constants.LocationActions.SELECT_WORK))){
destinationLayout.setVisibility(View.GONE);
selectedEditText = destination;
source.setText("");
source.setHint(getString(R.string.select_location));
} else{
destinationLayout.setVisibility(View.VISIBLE);
llSource.setVisibility(View.VISIBLE);
source.setHint(getString(R.string.pickup_location));
selectedEditText = source;
}
}
presenter.address();
}
private void setLocationText(String address, LatLng latLng, boolean isLocationRvClick,
boolean isSettingLocationClick) {
if (address != null && latLng != null) {
isEditable = false;
selectedEditText.setText(address);
isEditable = true;
if (selectedEditText.getTag().equals("source")) {
s_address = address;
s_latitude = latLng.latitude;
s_longitude = latLng.longitude;
MvpApplication.RIDE_REQUEST.put(Constants.RIDE_REQUEST.SRC_ADD, address);
MvpApplication.RIDE_REQUEST.put(Constants.RIDE_REQUEST.SRC_LAT, latLng.latitude);
MvpApplication.RIDE_REQUEST.put(Constants.RIDE_REQUEST.SRC_LONG, latLng.longitude);
}
if (selectedEditText.getTag().equals("destination")) {
MvpApplication.RIDE_REQUEST.put(Constants.RIDE_REQUEST.DEST_ADD, address);
MvpApplication.RIDE_REQUEST.put(Constants.RIDE_REQUEST.DEST_LAT, latLng.latitude);
MvpApplication.RIDE_REQUEST.put(Constants.RIDE_REQUEST.DEST_LONG, latLng.longitude);
if (isLocationRvClick) {
// Done functionality called...
setResult(Activity.RESULT_OK, new Intent());
finish();
}
}
} else {
isEditable = false;
selectedEditText.setText("");
locationsRv.setVisibility(View.GONE);
isEditable = true;
if (selectedEditText.getTag().equals("source")) {
MvpApplication.RIDE_REQUEST.remove(Constants.RIDE_REQUEST.SRC_ADD);
MvpApplication.RIDE_REQUEST.remove(Constants.RIDE_REQUEST.SRC_LAT);
MvpApplication.RIDE_REQUEST.remove(Constants.RIDE_REQUEST.SRC_LONG);
}
if (selectedEditText.getTag().equals("destination")) {
MvpApplication.RIDE_REQUEST.remove(Constants.RIDE_REQUEST.DEST_ADD);
MvpApplication.RIDE_REQUEST.remove(Constants.RIDE_REQUEST.DEST_LAT);
MvpApplication.RIDE_REQUEST.remove(Constants.RIDE_REQUEST.DEST_LONG);
}
}
if (isSettingLocationClick) {
hideKeyboard();
locationsRv.setVisibility(View.GONE);
}
}
#Override
public void onResume() {
super.onResume();
if (!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting()) {
Log.v("Google API", "Connecting");
mGoogleApiClient.connect();
}
}
#Override
public void onPause() {
super.onPause();
if (mGoogleApiClient.isConnected()) {
Log.v("Google API", "Dis-Connecting");
mGoogleApiClient.disconnect();
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#OnClick({R.id.source, R.id.destination, R.id.reset_source, R.id.reset_destination, R.id.home_address_layout, R.id.work_address_layout})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.source:
break;
case R.id.destination:
break;
case R.id.reset_source:
selectedEditText = source;
source.requestFocus();
setLocationText(null, null, isLocationRvClick, isSettingLocationClick);
break;
case R.id.reset_destination:
destination.requestFocus();
selectedEditText = destination;
setLocationText(null, null, isLocationRvClick, isSettingLocationClick);
break;
case R.id.home_address_layout:
if (home != null)
setLocationText(home.getAddress(),
new LatLng(home.getLatitude(), home.getLongitude()),
isLocationRvClick, isSettingLocationClick);
break;
case R.id.work_address_layout:
if (work != null)
setLocationText(work.getAddress(),
new LatLng(work.getLatitude(), work.getLongitude()),
isLocationRvClick, isSettingLocationClick);
break;
}
}
#Override
public void onCameraIdle() {
try {
CameraPosition cameraPosition = mGoogleMap.getCameraPosition();
if (isEnableIdle) {
String address = getAddress(cameraPosition.target);
System.out.println("onCameraIdle " + address);
hideKeyboard();
setLocationText(address, cameraPosition.target, isLocationRvClick, isSettingLocationClick);
}
isEnableIdle = true;
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onCameraMove() {
System.out.println("LocationPickActivity.onCameraMove");
}
#Override
public void onMapReady(GoogleMap googleMap) {
try {
// Google map custom style...
googleMap.setMapStyle(MapStyleOptions.loadRawResourceStyle(this, R.raw.style_json));
} catch (Resources.NotFoundException e) {
Log.d("Map:Style", "Can't find style. Error: ");
}
this.mGoogleMap = googleMap;
getLocationPermission();
updateLocationUI();
getDeviceLocation();
}
void getDeviceLocation() {
try {
if (mLocationPermissionGranted) {
Task<Location> locationResult = mFusedLocationProviderClient.getLastLocation();
locationResult.addOnCompleteListener(this, task -> {
if (task.isSuccessful() && task.getResult() != null) {
mLastKnownLocation = task.getResult();
mGoogleMap.moveCamera(CameraUpdateFactory
.newLatLngZoom(new LatLng(
mLastKnownLocation.getLatitude(),
mLastKnownLocation.getLongitude()
), DEFAULT_ZOOM));
} else {
Log.d("Map", "Current location is null. Using defaults.");
Log.e("Map", "Exception: %s", task.getException());
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);
}
});
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage());
}
}
public void getLocationPermission() {
if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
mLocationPermissionGranted = true;
else
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_ACCESS_FINE_LOCATION);
}
private void updateLocationUI() {
if (mGoogleMap == null) return;
try {
if (mLocationPermissionGranted) {
mGoogleMap.setMyLocationEnabled(true);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);
mGoogleMap.setOnCameraMoveListener(this);
mGoogleMap.setOnCameraIdleListener(this);
} else {
mGoogleMap.setMyLocationEnabled(false);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);
mLastKnownLocation = null;
getLocationPermission();
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage());
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
mLocationPermissionGranted = false;
if (requestCode == REQUEST_ACCESS_FINE_LOCATION)
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
updateLocationUI();
getDeviceLocation();
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
Log.v("Google API Callback", "Connection Suspended");
Log.v("Code", String.valueOf(i));
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.v("Error Code", String.valueOf(connectionResult.getErrorCode()));
Toast.makeText(this, "API_NOT_CONNECTED", Toast.LENGTH_SHORT).show();
}
#Override
public void onBackPressed() {
if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED)
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
else super.onBackPressed();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.location_pick_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_done:
if (!TextUtils.isEmpty(actionName) && actionName.equals(Constants.LocationActions.SELECT_HOME) || actionName.equals(Constants.LocationActions.SELECT_WORK)){
Intent intent = new Intent();
intent.putExtra(Constants.RIDE_REQUEST.SRC_ADD, s_address);
intent.putExtra(Constants.RIDE_REQUEST.SRC_LAT, s_latitude);
intent.putExtra(Constants.RIDE_REQUEST.SRC_LONG, s_longitude);
setResult(Activity.RESULT_OK, intent);
finish();
} else {
setResult(Activity.RESULT_OK, new Intent());
finish();
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onSuccess(AddressResponse address) {
if (address.getHome().isEmpty()) homeAddressLayout.setVisibility(View.GONE);
else {
home = address.getHome().get(address.getHome().size() - 1);
homeAddress.setText(home.getAddress());
homeAddressLayout.setVisibility(View.VISIBLE);
}
if (address.getWork().isEmpty()) workAddressLayout.setVisibility(View.GONE);
else {
work = address.getWork().get(address.getWork().size() - 1);
workAddress.setText(work.getAddress());
workAddressLayout.setVisibility(View.VISIBLE);
}
}
#Override
public void onError(Throwable e) {
handleError(e);
}
#Override
protected void onDestroy() {
presenter.onDetach();
super.onDestroy();
}
}
public class PlacesAutoCompleteAdapter extends RecyclerView.Adapter<PlacesAutoCompleteAdapter.PredictionHolder> implements Filterable {
private static final String TAG = "PlacesAutoAdapter";
private ArrayList<PlaceAutocomplete> mResultList = new ArrayList<>();
private GoogleApiClient mGoogleApiClient;
private LatLngBounds mBounds;
private Context mContext;
private int layout;
private CharacterStyle STYLE_BOLD;
private CharacterStyle STYLE_NORMAL;
PlacesClient placesClient =null;
public PlacesAutoCompleteAdapter(Context context, int resource, GoogleApiClient googleApiClient, LatLngBounds bounds) {
mContext = context;
layout = resource;
mGoogleApiClient = googleApiClient;
mBounds = bounds;
STYLE_BOLD = new StyleSpan(Typeface.BOLD);
STYLE_NORMAL = new StyleSpan(Typeface.NORMAL);
if (!Places.isInitialized()) {
Places.initialize(context, context.getString(R.string.google_api_key));
}
placesClient = Places.createClient(context);
}
public void setBounds(LatLngBounds bounds) {
mBounds = bounds;
}
/**
* Returns the filter for the current set of autocomplete results.
*/
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// Skip the autocomplete query if no constraints are given.
if (constraint != null) {
// Query the autocomplete API for the (constraint) search string.
mResultList = getAutocomplete(constraint);
if (mResultList != null) {
// The API successfully returned results.
results.values = mResultList;
results.count = mResultList.size();
}
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
// The API returned at least one result, update the data.
notifyDataSetChanged();
} else {
// The API did not return any results, invalidate the data set.
//notifyDataSetInvalidated();
}
}
};
}
private ArrayList getAutocomplete(CharSequence constraint) {
if (mGoogleApiClient.isConnected()) {
Log.i("", "Starting autocomplete query for: " + constraint);
// Create a new token for the autocomplete session. Pass this to FindAutocompletePredictionsRequest,
fetchPlace()).
AutocompleteSessionToken token = AutocompleteSessionToken.newInstance();
FindAutocompletePredictionsRequest request = FindAutocompletePredictionsRequest.builder()
.setTypeFilter(TypeFilter.ADDRESS)
.setSessionToken(token)
.setQuery(constraint.toString())
.build();
ArrayList<PlaceAutocomplete> resultList = new ArrayList<>();
placesClient.findAutocompletePredictions(request).addOnSuccessListener((response) -> {
for (AutocompletePrediction prediction : response.getAutocompletePredictions()) {
Log.i(TAG, prediction.getPlaceId());
Log.i(TAG, prediction.getPrimaryText(null).toString());
resultList.add(new PlaceAutocomplete(prediction.getPlaceId(), prediction.getPrimaryText(STYLE_NORMAL),
prediction.getFullText(STYLE_BOLD)));
}
}).addOnFailureListener((exception) -> {
return resultList;
}
Log.e(TAG, "Google API client is not connected for autocomplete query.");
return null;
}
#NonNull
#Override
public PredictionHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View convertView = Objects.requireNonNull(layoutInflater).inflate(layout, viewGroup, false);
return new PredictionHolder(convertView);
}
#Override
public void onBindViewHolder(#NonNull PredictionHolder mPredictionHolder, final int i) {
mPredictionHolder.area.setText(mResultList.get(i).area);
mPredictionHolder.address.setText(mResultList.get(i).address.toString()
.replace(mResultList.get(i).area + ", ", ""));
}
#Override
public int getItemCount() {
return (mResultList == null) ? 0 : mResultList.size();
}
public PlaceAutocomplete getItem(int position) {
return mResultList.get(position);
}
class PredictionHolder extends RecyclerView.ViewHolder {
private TextView address, area;
PredictionHolder(View itemView) {
super(itemView);
area = itemView.findViewById(R.id.area);
address = itemView.findViewById(R.id.address);
}
}
public class PlaceAutocomplete {
public CharSequence placeId;
public CharSequence address, area;
PlaceAutocomplete(CharSequence placeId, CharSequence area, CharSequence address) {
this.placeId = placeId;
this.area = area;
this.address = address;
}
#Override
public String toString() {
return area.toString();
}
}
}
The Place Picker is deprecated as of January 29, 2019. This feature will be turned off on July 29, 2019, and will no longer be available after that date. You must install the compatibility library to continue using the Place Picker during the deprecation period. Once the deprecation period has ended, the Place Picker will no longer be available for use (including the version in the compatibility library).
I'm Using Yandex Translator in my app, it works great if i'm using Activity, But when i add it to fragment , the app crashes before the launch.
Also no errors shown in the code , like everything is good, what could be the problem :
I looked for similar answers here, but i got nothing, no one had this issue before using fragments.
And here is the code for fragment :
public class FavoritesFragment extends Fragment implements TextToSpeech.OnInitListener{
private TextView header, toText, toLabel, fromLabel;
private ImageView micFrom, volFrom, volTo, reverse;
private EditText fromText;
private CircleButton convertBTN;
private CircleButton convertLayout;
private final int REQ_CODE_SPEECH_INPUT = 100;
private final int SR_CODE = 123;
private String ENGLISH_CONSTANT = "";
private String TURKISH_CONSTANT = "";
private String ENGLISH_CONVERT = "";
private String TURKISH_CONVERT = "";
private String TURKISH_CODE = "";
private String currentFrom = "";
TextToSpeech ttsEnglish, ttsTURKISH;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_favorites, container, false);
setUpInitialConstants();
setUpInteraction();
setUpSpeakingListeners();
setUpListeners();
return v;
}
private void setUpInitialConstants() {
ENGLISH_CONSTANT = ("ENGLISH");
TURKISH_CONSTANT = ("TURKISH");
ENGLISH_CONVERT = ("en") + "-" + ("tr");//"en-zh";
TURKISH_CONVERT = ("tr") + "-" + ("en");
//"zh-en";
TURKISH_CODE = ("tr");
currentFrom = ENGLISH_CONSTANT;
}
private void setUpSpeakingListeners() {
ttsEnglish = new TextToSpeech(getContext().getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
// TODO Auto-generated method stub
if (status == TextToSpeech.SUCCESS) {
int result = ttsEnglish.setLanguage(Locale.ENGLISH);
if (result == TextToSpeech.LANG_MISSING_DATA ||
result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("error", "This Language is not supported");
} else {
//ConvertTextToSpeech();
}
} else
Log.e("error", "Initilization Failed!");
}
});
ttsTURKISH = new TextToSpeech(getContext().getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
// TODO Auto-generated method stub
if (status == TextToSpeech.SUCCESS) {
Locale locale = new Locale("tr-TR");
int result = ttsTURKISH.setLanguage(locale);
if (result == TextToSpeech.LANG_MISSING_DATA ||
result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("error", "not supported");
} else {
//ConvertTextToSpeech();
}
} else
Log.e("error", "Initilization Failed!");
}
});
}
#SuppressLint("ClickableViewAccessibility")
private void setUpListeners() {
convertLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Vibrator vibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(200);
callReverse();
}
});
micFrom.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Vibrator vibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(200);
askSpeechInput(currentFrom);
}
});
volFrom.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Vibrator vibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(200);
ConvertTextToSpeech(currentFrom, fromText.getText().toString());
}
});
volTo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Vibrator vibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(200);
String currentFromR = reverseCurrentFrom(currentFrom);
ConvertTextToSpeech(currentFromR, toText.getText().toString());
}
});
convertBTN.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Vibrator vibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(200);
if (currentFrom.equals(ENGLISH_CONSTANT))
translateText(fromText.getText().toString(), ENGLISH_CONVERT);
else
translateText(fromText.getText().toString(), TURKISH_CONVERT);
}
});
toText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Vibrator vibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(200);
if (copyToClipboard(getContext().getApplicationContext(), toText.getText().toString())) {
if (currentFrom.equals(ENGLISH_CONSTANT)) {
Toast.makeText(getContext().getApplicationContext(), ("copied"), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getContext().getApplicationContext(), (" copied successfully "), Toast.LENGTH_SHORT).show();
}
}
}
});
fromText.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
fromText.setFocusableInTouchMode(true);
return false;
}
});
}
private String reverseCurrentFrom(String currentFrom) {
if (currentFrom.equals(ENGLISH_CONSTANT)) {
return TURKISH_CONSTANT;
} else return ENGLISH_CONSTANT;
}
private void callReverse() {
if (currentFrom.equals(ENGLISH_CONSTANT)) {
currentFrom = TURKISH_CONSTANT;
//header.setText(getString(R.string.convertHeaderR));
fromLabel.setText(("TURKISH"));
fromText.setHint(("push to talk"));
toLabel.setText(("English"));
toText.setText(("Click translate Button to get English text"));
} else {
currentFrom = ENGLISH_CONSTANT;
//header.setText(getString(R.string.convertHeader));
fromLabel.setText(("English"));
fromText.setHint(("Speak or type text here"));
toLabel.setText(("TURKISH"));
toText.setText(("click to translate"));
}
fromText.setText("");
fromText.setFocusable(false);
}
private void setUpInteraction() {
this.getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
toText = getView().findViewById(R.id.toText);
toLabel = getView().findViewById(R.id.toLabel);
fromLabel = getView().findViewById(R.id.fromLabel);
micFrom = getView().findViewById(R.id.micFrom);
volFrom = getView().findViewById(R.id.volFrom);
volTo = getView().findViewById(R.id.toVol);
convertBTN = getView().findViewById(R.id.convertBTN);
fromText = getView().findViewById(R.id.fromText);
convertLayout = getView().findViewById(R.id.swapLanguage);
fromText.setFocusable(false);
currentFrom = TURKISH_CONSTANT;
callReverse();
}
private void ConvertTextToSpeech(String lang_type, String text) {
if (text == null || "".equals(text)) {
if (lang_type.equals(ENGLISH_CONSTANT)) {
text = ("Content not available");
} else {
text = ("something wrong !");
}
}
if (lang_type.equals(ENGLISH_CONSTANT)) {
ttsEnglish.speak(text, TextToSpeech.QUEUE_FLUSH, null);
} else {
ttsTURKISH.speak(text, TextToSpeech.QUEUE_FLUSH, null);
}
}
private void askSpeechInput(String lang_type) {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
if (lang_type.equals(ENGLISH_CONSTANT)) {
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.ENGLISH);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT,
"Hi speak something");
startActivityForResult(intent, REQ_CODE_SPEECH_INPUT);
} else {
//Specify language
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, TURKISH_CODE);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, TURKISH_CODE);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, TURKISH_CODE);
intent.putExtra(RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES, TURKISH_CODE);
intent.putExtra(RecognizerIntent.EXTRA_ONLY_RETURN_LANGUAGE_PREFERENCE, TURKISH_CODE);
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, TURKISH_CODE);
intent.putExtra(RecognizerIntent.EXTRA_RESULTS, TURKISH_CODE);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, ("speak please"));
startActivityForResult(intent, SR_CODE);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQ_CODE_SPEECH_INPUT: {
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> result = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
fromText.setText(result.get(0));
}
break;
}
case SR_CODE: {
if (resultCode == RESULT_OK) {
if (data != null) {
ArrayList<String> nBestList = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
String bestResult = nBestList.get(0);
fromText.setText(bestResult);
}
}
break;
}
}
if (currentFrom.equals(ENGLISH_CONSTANT))
translateText(fromText.getText().toString(), ENGLISH_CONVERT);
else
translateText(fromText.getText().toString(), TURKISH_CONVERT);
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
} else {
Log.e("TTS", "Initialization failed");
}
}
String text_to_return = "";
private String translateText(final String text, final String lang) {
class getQData extends AsyncTask<String, String, String> {
ProgressDialog loading;
String ROOT_URL = "https://translate.yandex.net";
Retrofit adapter = new Retrofit.Builder()
.baseUrl(ROOT_URL)
.addConverterFactory(JacksonConverterFactory.create())
.build();
APICalls api = adapter.create(APICalls.class);
#Override
protected void onPreExecute() {
super.onPreExecute();
showPD();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
#Override
protected String doInBackground(String... params) {
text_to_return = "";
String key = translator_Constants.MY_KEY;
Call<TranslateResponse> call = api.translate(key, text, lang);
call.enqueue(new Callback<TranslateResponse>() {
#Override
public void onResponse(retrofit.Response<TranslateResponse> response, Retrofit retrofit) {
//loading.dismiss();
hidePD();
Log.d("succ", "onResponse:code" + String.valueOf(response.code()));
Log.d("error mesg", String.valueOf(response.message()));
switch (response.code()) {
case 200:
TranslateResponse tr = response.body();
text_to_return = tr.getText().get(0);
toText.setText(text_to_return);
String currentFromR = reverseCurrentFrom(currentFrom);
ConvertTextToSpeech(currentFromR, toText.getText().toString());
break;
default:
if (currentFrom.equals(ENGLISH_CONSTANT))
Toast.makeText(getContext().getApplicationContext(), ("Please Try Again"), Toast.LENGTH_SHORT).show();
else
Toast.makeText(getContext().getApplicationContext(), ("again"), Toast.LENGTH_SHORT).show();
break;
}
}
#Override
public void onFailure(Throwable t) {
pd.dismiss();
Log.d("retro error", t.getMessage());
if (currentFrom.equals(ENGLISH_CONSTANT))
Toast.makeText(getContext().getApplicationContext(), ("Failed to Convert!Check Internet Connection"), Toast.LENGTH_SHORT).show();
else
Toast.makeText(getContext().getApplicationContext(), ("no connexion"), Toast.LENGTH_SHORT).show();
}
});
return text_to_return;
}
}
getQData ru = new getQData();
try {
ru.execute().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return text_to_return;
}
ProgressDialog pd;
private void showPD() {
pd = new ProgressDialog(getActivity());
if (currentFrom.equals(ENGLISH_CONSTANT)) {
pd.setMessage(("Patience, We are translating…"));
} else {
pd.setMessage(("translating ..."));
}
pd.show();
}
private void hidePD() {
pd.dismiss();
}
public boolean copyToClipboard(Context context, String text) {
try {
int sdk = android.os.Build.VERSION.SDK_INT;
if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context
.getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(text);
} else {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context
.getSystemService(CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData
.newPlainText("copy", text);
clipboard.setPrimaryClip(clip);
}
return true;
} catch (Exception e) {
return false;
}
}
}
Call setupInteraction() from onViewCreated(), not from onCreateView(). You are trying to use getView(), which will not work until onCreateView() returns.
I am developing an app where I am using android's dialog for granting dangerous permissions. And when I click button for login on LoginActivity I go to Main activity and dialog is show. But when I press BACK button, again this dialog appears! This is my MainActivity(Just to say that my launcher activity is MAinActivity, not LoginActivity):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
setContentView(R.layout.activity_main);
Bugsnag.init(this, BUGSNAG_API_KEY);
company_name = (TextView) findViewById(R.id.company_name);
aUsername = (TextView) findViewById(R.id.username);
company_name.setTextColor(ContextCompat.getColor(this, R.color.colorBlue));
// aUsername.setTextColor(ContextCompat.getColor(this, R.color.colorBlack));
toolbarImage = (ImageView) findViewById(R.id.image_id);
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setDisplayShowHomeEnabled(false);
}
getDataForToolbar();
checkIfServiceWorking();
askingForPermissionInManifest();
alertForEnablingGPS();
logoutWhenCompanyDisabled();
String token = FirebaseInstanceId.getInstance().getToken();
Log.d("FCM", "Fire_base token is: " + token);
readTokenFromSharedPreferences();
initializeInjectorListIcons();
initializeListIcons();
initializeInjector();
initialize();
BottomBar bottomBar = (BottomBar) findViewById(R.id.bottomBar);
bottomBar.setOnTabSelectListener(new OnTabSelectListener() {
#Override
public void onTabSelected(#IdRes int tabId) {
getFragment(tabId);
}
});
}
public static Context getContx() {
return mContext;
}
private void checkIfServiceWorking() {
mLocationService = new LocationService(getContx());
mServiceIntent = new Intent(getContx(), mLocationService.getClass());
if (!isMyServiceRunning(LocationService.class)){
startService(mServiceIntent);
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
Log.i ("isMyServiceRunning?", true + "");
return true;
}
}
Log.i ("isMyServiceRunning?", false + "");
return false;
}
private void initializeInjector() {
this.accountComponent = DaggerAccountComponent.builder()
.applicationComponent(getApplicationComponent())
.activityModule(getActivityModule())
.accountModule(new AccountModule())
.build();
}
public void initialize() {
this.getComponent(AccountComponent.class).inject(this);
this.accountPresenter.setView(this);
this.accountPresenter.initialize();
}
public void initializeInjectorListIcons() {
this.accountComponent = DaggerAccountComponent.builder()
.applicationComponent(getApplicationComponent())
.activityModule(getActivityModule())
.listIconsModule(new ListIconsModule())
.build();
}
public void initializeListIcons() {
this.getComponent(AccountComponent.class).inject(this);
this.listIconsPresenter.initializeListIcons();
}
#Override
public AccountComponent getComponent() {
return accountComponent;
}
#Override
public void viewAccount(AccountModel accountModel) {
if (accountModel != null) {
if (accountModel.getRoles().getName().equals(getResources().getString(R.string.role_team_leader)) || (accountModel.getRoles().getName().equals(getResources().getString(R.string.role_user)))){
Gson account_json = new Gson();
String account = account_json.toJson(accountModel);
SharedPreferences sharedPreferences = getSharedPreferences(getResources().getString(R.string.Account_json), MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(getResources().getString(R.string.account_json), account);
editor.apply();
List<ButtonModel> arrayListButton = accountModel.getLayout().getButtons();
if (accountModel.getRoles().getName().equals(getResources().getString(R.string.role_user)) || accountModel.getRoles().getName().equals(getResources().getString(R.string.role_team_leader)) && arrayListButton.size() != 0) {
showLanguageSettings();
addFragment(R.id.fragment_container, new DashboardFragment());
goingToFragmentWithNotificationClick();
FirebaseMessaging.getInstance().subscribeToTopic(accountModel.getUuid());
for (CompanyModel com : accountModel.getCompanies()) {
String teamUuid = com.getTeam().getUuid();
String language = com.getLanguage().getCode();
SharedPreferences sharedPreferences1 = getSharedPreferences("language", MODE_PRIVATE);
SharedPreferences.Editor editor1 = sharedPreferences1.edit();
editor1.putString("prefLanguage", language);
editor1.apply();
if (teamUuid != null) {
FirebaseMessaging.getInstance().subscribeToTopic(teamUuid);
}
}
FirebaseMessaging.getInstance().subscribeToTopic(accountModel.getRoles().getUuid());
} else if (arrayListButton.size() == 0 && accountModel.getRoles().getName().equals(getResources().getString(R.string.role_user)) || accountModel.getRoles().getName().equals(getResources().getString(R.string.role_team_leader))) {
addFragment(R.id.fragment_container, new EmptyListButtonFragment());
}
getDataForToolbar();
}
else {
removeTokenAndWrongAccountFromSharedPreferences();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_log_out) {
if (isNetworkConnected()) {
unsubscribingFromFirebase();
removeTokenAndAccountFromSharedPreferences();
shouldRestart = false;
stopService(mServiceIntent);
Log.i("MAIN_ACTIVITY", "Logout!");
Log.d("MAIN_ACTIVITY " , "Internet access ");
}
else {
Toast.makeText(getApplicationContext(), getResources().getString(R.string.need_internet), Toast.LENGTH_SHORT).show();
}
}
if (id == R.id.action_fcmToken) {
TextView textView = new TextView(this);
textView.setHeight(300);
textView.setText(FirebaseInstanceId.getInstance().getToken());
textView.setTextIsSelectable(true);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Token");
builder.setView(textView)
.setCancelable(true)
.show();
}
if (id == R.id.versionInfo) {
getCurrentAppVersionInfo();
}
if (id == R.id.LocationInfo){
getLocationInfo();
}
return super.onOptionsItemSelected(item);
}
public void readTokenFromSharedPreferences() {
SharedPreferences sharedPreferences = getSharedPreferences(getResources().getString(R.string.token_preferences), MODE_PRIVATE);
final String strPref = sharedPreferences.getString(getResources().getString(R.string.token), null);
if (strPref == null) {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
}
public void removeTokenAndAccountFromSharedPreferences() {
SharedPreferences sharedPreferences = getSharedPreferences(getResources().getString(R.string.token_preferences), MODE_PRIVATE);
sharedPreferences.edit().remove(getResources().getString(R.string.token)).apply();
final String strPref = sharedPreferences.getString(getResources().getString(R.string.token), null);
SharedPreferences sharedPreferencesAccount = getSharedPreferences(getResources().getString(R.string.Account_json), MODE_PRIVATE);
sharedPreferencesAccount.edit().remove(getResources().getString(R.string.account_json)).apply();
final String accountPref = sharedPreferencesAccount.getString(getResources().getString(R.string.account_json), null);
if (strPref == null && accountPref == null) {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
}
public void removeTokenAndWrongAccountFromSharedPreferences() {
SharedPreferences sharedPreferences = getSharedPreferences(getResources().getString(R.string.token_preferences), MODE_PRIVATE);
String strPref;
strPref = sharedPreferences.getString(getResources().getString(R.string.token), null);
SharedPreferences sharedPreferencesAccount = getSharedPreferences(getResources().getString(R.string.Account_json), MODE_PRIVATE);
String accountPref;
accountPref=sharedPreferencesAccount.getString(getResources().getString(R.string.account_json), null);
if(strPref != null || accountPref != null){
sharedPreferences.edit().remove(getResources().getString(R.string.token)).apply();
sharedPreferencesAccount.edit().remove(getResources().getString(R.string.account_json)).apply();
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
finish();
Toast.makeText(MainActivity.this, getResources().getString(R.string.message_for_roles), Toast.LENGTH_LONG).show();
}
}
public void getFragment(int id) {
switch (id) {
case R.id.tab_menu_dashboard:
addFragment(R.id.fragment_container, new DashboardFragment());
break;
case R.id.tab_menu_messages:
addFragment(R.id.fragment_container, new MessagesFragment());
break;
case R.id.tab_menu_team:
addFragment(R.id.fragment_container, new TeamFragment());
break;
case R.id.tab_menu_incidents:
addFragment(R.id.fragment_container, new IncidentsFragment());
break;
}
}
#Override
protected void onResume() {
readTokenFromSharedPreferences();
super.onResume();
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onStop() {
super.onStop();
if (alertDialog != null) {
alertDialog.dismiss();
}
}
#Override
protected void onPause() {
super.onPause();
if (alertDialog != null) {
alertDialog.dismiss();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (alertDialog != null && alertDialog.isShowing()) {
alertDialog.dismiss();
}
stopService(mServiceIntent);
Log.i("MAIN_ACTIVITY", "onDestroy!");
}
public void goingToFragmentWithNotificationClick() {
String clickNotification = getIntent().getStringExtra("notification_type");
String clickReportActivity = getIntent().getStringExtra("report_activity");
if (clickNotification != null) {
if (mAccount != null) {
if (mAccount.getRoles().getName().equals(getResources().getString(R.string.role_team_leader))) {
if (clickNotification.equals("incident_notify")) {
addFragment(R.id.fragment_container, new IncidentsFragment());
} else if (clickNotification.equals("chat_message")) {
addFragment(R.id.fragment_container, new MessagesFragment());
}
} else {
if (clickNotification.equals("chat_message")) {
addFragment(R.id.fragment_container, new MessagesFragment());
}
}
}
}
if(clickReportActivity!=null){
addFragment(R.id.fragment_container, new IncidentsFragment());
}
}
public void picassoLoader(Context context, ImageView imageView, String url) {
Picasso.with(context)
.load(url)
.resize(70, 58)
.transform(new RoundedTransformation(8, 0))
.into(imageView);
}
private void getCurrentAppVersionInfo() {
int versionCode = -1;
String versionName = "";
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
versionCode = packageInfo.versionCode;
versionName = packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
String alert1 = "Version Code: " + versionCode;
String alert2 = "Version Name: " + versionName;
builder.setMessage(alert1 + "\n" + alert2).show();
}
#SuppressLint("SetTextI18n")
public void getDataForToolbar() {
SharedPreferences sharedPreferences = getSharedPreferences(getResources().getString(R.string.Account_json), Context.MODE_PRIVATE);
final String account = sharedPreferences.getString(getResources().getString(R.string.account_json), null);
if (account != null) {
Gson gson = new Gson();
mAccount = gson.fromJson(account, AccountModel.class);
for (CompanyModel com : mAccount.getCompanies()) {
String name = com.getName();
company_name.setText(name);
logo_url = com.getLogo_url();
}
if (logo_url == null || logo_url.isEmpty()) {
Picasso
.with(this)
.load(R.drawable.default_company)
.resize(70, 58)
.transform(new RoundedTransformation(8, 0))
.into(toolbarImage);
} else {
picassoLoader(this, toolbarImage, logo_url);
}
String username = mAccount.getUsername();
if(mAccount.getStatus()){
aUsername.setText(username + "/" + getResources().getString(R.string.on_duty));
aUsername.setBackgroundColor(ContextCompat.getColor(mContext, R.color.colorGreen));
}else{
aUsername.setText(username + "/" + getResources().getString(R.string.off_duty));
aUsername.setBackgroundColor(ContextCompat.getColor(mContext, R.color.colorWhite));
}
}
}
public void alertForEnablingGPS() {
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
!lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle(getResources().getString(R.string.enable_location_Service));
builder.setMessage(getResources().getString(R.string.GPS));
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
});
alertDialog = builder.create();
alertDialog.setCanceledOnTouchOutside(false);
alertDialog.show();
}
}
public void logoutWhenCompanyDisabled() {
String logout = getIntent().getStringExtra("notification_type");
if (logout != null) {
if (logout.equals("company_disabled")) {
unsubscribingFromFirebase();
removeTokenAndAccountFromSharedPreferences();
}
}
}
public void unsubscribingFromFirebase() {
if (mAccount != null) {
if (mAccount.getRoles().getName().equals(getResources().getString(R.string.role_user)) || mAccount.getRoles().getName().equals(getResources().getString(R.string.role_team_leader))) {
FirebaseMessaging.getInstance().unsubscribeFromTopic(mAccount.getUuid());
FirebaseMessaging.getInstance().unsubscribeFromTopic(mAccount.getRoles().getUuid());
for (CompanyModel com : mAccount.getCompanies()) {
String teamUuid = com.getTeam().getUuid();
if (teamUuid != null) {
FirebaseMessaging.getInstance().unsubscribeFromTopic(teamUuid);
}
Log.d("FCM", "UnSubscribed on team Uuid: " + teamUuid);
}
}
}
}
public class RoundedTransformation implements com.squareup.picasso.Transformation {
private final int radius;
private final int margin;
public RoundedTransformation(final int radius, final int margin) {
this.radius = radius;
this.margin = margin;
}
#Override
public Bitmap transform(final Bitmap source) {
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
Bitmap output = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
canvas.drawRoundRect(new RectF(margin, margin, source.getWidth() - margin, source.getHeight() - margin), radius, radius, paint);
if (source != output) {
source.recycle();
}
return output;
}
#Override
public String key() {
return "rounded";
}
}
private boolean isNetworkConnected() {
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
public void askingForPermissionInManifest(){
if((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) != PackageManager.PERMISSION_GRANTED){
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)){
}else{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.SEND_SMS, Manifest.permission.CALL_PHONE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d("all", "good");
alertForEnablingGPS();
restartActivity();
} else {
Log.d("need location", "need permissions");
}
break;
}
}
}
This is LogIn activity:
public class LoginActivity extends BaseActivity implements HasComponent<LoginComponent>, TokenView {
Credentials credentials;
TextInputEditText username;
TextInputEditText password;
Button login;
Configuration config;
private LoginComponent loginComponent;
#Inject LoginPresenter loginPresenter;
static Context mContext;
#SuppressLint("WrongViewCast")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mContext = this;
checkLanguage();
username = (TextInputEditText)findViewById(R.id.username);
password = (TextInputEditText)findViewById(R.id.password);
credentials = new Credentials();
login = (Button) findViewById(R.id.btn_login);
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String getUsername = username.getText().toString();
String getPassword = password.getText().toString();
if (getUsername.length()>0 && getPassword.length()>0 ) {
credentials.setUsername(getUsername);
credentials.setPassword(getPassword);
allOperations();
} else {
Toast.makeText(LoginActivity.this, R.string.empty_fields , Toast.LENGTH_LONG).show();
}
}
});
}
private void initializeInjector() {
this.loginComponent = DaggerLoginComponent.builder()
.applicationComponent(getApplicationComponent())
.activityModule(getActivityModule())
.loginModule(new LoginModule(this.credentials))
.build();
}
public void initialize () {
this.getComponent(LoginComponent.class).inject(this);
this.loginPresenter.setView(this);
this.loginPresenter.initialize(this.credentials);
}
#Override
public void viewToken(TokenModel tokenModel) {
if (tokenModel != null) {
String tokMod = tokenModel.getToken();
SharedPreferences sharedPreferences = getSharedPreferences(getResources().getString(R.string.token_preferences), MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(getResources().getString(R.string.token), tokMod);
editor.apply();
Log.d("Token na logovanju je: ", "TokenLogo" + tokMod);
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
}
public void allOperations () {
initializeInjector();
initialize();
}
#Override
public LoginComponent getComponent() {
return loginComponent;
}
#Override
public void showLoading() {
}
#Override
public void hideLoading() {
}
#Override
public void showRetry() {
}
#Override
public void hideRetry() {
}
#Override
public void showError(int message) {
Toast.makeText(LoginActivity.this, message , Toast.LENGTH_LONG).show();
}
#Override
public Context context() {
return null;
}
#Override public void onDestroy() {
super.onDestroy();
if (loginPresenter != null) {
this.loginPresenter.destroy();
}
}
public void checkLanguage(){
SharedPreferences sharedPreferences = getSharedPreferences("language", MODE_PRIVATE);
String language = sharedPreferences.getString("prefLanguage", null);
config = new Configuration(getResources().getConfiguration());
if(language!=null){
if(language.equals("en")){
config.locale = Locale.ENGLISH;
}
if(language.equals("sr")){
config.locale = new Locale("sr");
}
getResources().updateConfiguration(config, getResources().getDisplayMetrics());
onConfigurationChanged(config);
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
public static void downloadFile(String uRl, String name_image) {
File direct = new File(Environment.getExternalStorageDirectory() + "/icons");
if (!direct.exists()) {
direct.mkdirs();
}
DownloadManager mgr = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE);
Uri downloadUri = Uri.parse(uRl);
DownloadManager.Request request = new DownloadManager.Request(
downloadUri);
request.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_WIFI
| DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false).setTitle("Demo")
.setDescription("Incident icons for dashboard.")
.setDestinationInExternalPublicDir("/icons", name_image);
mgr.enqueue(request);
}}
Could anyone helps me how to fix this problem, how to get this dialog only when I login into Main activity, not when I click BACK button? Thanks in advance.
I have implemented Twilio in my android app for outgoing and incoming calls. But I'm facing an issue while getting incoming call with the background service. The issue is that I get calls in first 30-40 mins only. After sometime phone stops getting incoming calls. I tried so much. Please respond me soon. I'm sharing code with you too.
I get token from a background service which generates token after a time period.
IncomingCallService.java
public class IncomingCallService extends Service implements LoginListener,
BasicConnectionListener, BasicDeviceListener, View.OnClickListener,
CompoundButton.OnCheckedChangeListener,
RadioGroup.OnCheckedChangeListener {
private static Handler handler, handler_login;
public IncomingPhone phone;
SharedPreferences login_details;
Vibrator vibrator;
Ringtone r;
Uri notification;
public static final String LOGIN_DETAILS = "XXXXXXXX";
AudioManager am;
Intent intent;
public static String DEFAULT_CLIENT_NAME = "developer";
static String Twilio_id = "",
INCOMING_AUTH_PHP_SCRIPT = MenuItems.INCOMING_AUTH_PHP_SCRIPT
+ MenuItems.Twilio_id;
Runnable newrun;
Activity context;
Context ctx;
static String op_id = "";
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
login_details = getSharedPreferences(LOGIN_DETAILS,
Context.MODE_PRIVATE);
if (login_details.contains("twilio_Id")) {
Twilio_id = login_details.getString("twilio_Id", "");
}
handler_login = new Handler();
handler_login.postDelayed(new Runnable() {
#Override
public void run() {
Login();
handler_login.postDelayed(this, 20000);
}
}, 1000);
}
public void Login() {
phone = IncomingPhone.getInstance(getApplicationContext());
phone.setListeners(this, this, this);
phone.login(DEFAULT_CLIENT_NAME, true, true);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.intent = intent;
// I know getIntent always return NULL in service
if (intent != null) {
op_id = intent.getStringExtra("operator_id");
onCallHandler();
}
return START_STICKY;
}
public void onCallHandler() {
handler = new Handler();
newrun = new Runnable() {
#Override
public void run() {
handler.removeCallbacks(newrun);
new IncomingTokenTask().execute();
if (phone.handleIncomingIntent(intent)) {
}
handler.postDelayed(this, 2000000);
}
};
handler.postDelayed(newrun, 8000000);
}
class IncomingTokenTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... params) {
IncomingPhone.capabilityToken = EntityUtils
.toString(entity);
}
}
The BasicPhone class of twilio
public class IncomingPhone implements DeviceListener, ConnectionListener {
private static final String TAG = "IncomingPhone";
static String decodedString = "";
static String capabilityToken = "";
// TODO: change this to point to the script on your public server
private static final String AUTH_PHP_SCRIPT = MenuItems.INCOMING_AUTH_PHP_SCRIPT+MenuItems.Twilio_id;
public interface LoginListener {
public void onLoginStarted();
public void onLoginFinished();
public void onLoginError(Exception error);
}
public interface BasicConnectionListener {
public void onIncomingConnectionDisconnected();
public void onConnectionConnecting();
public void onConnectionConnected();
public void onConnectionFailedConnecting(Exception error);
public void onConnectionDisconnecting();
public void onConnectionDisconnected();
public void onConnectionFailed(Exception error);
}
public interface BasicDeviceListener {
public void onDeviceStartedListening();
public void onDeviceStoppedListening(Exception error);
}
private static IncomingPhone instance;
public static final IncomingPhone getInstance(Context context) {
if (instance == null)
instance = new IncomingPhone(context);
return instance;
}
private final Context context;
private LoginListener loginListener;
private BasicConnectionListener basicConnectionListener;
private BasicDeviceListener basicDeviceListener;
private static boolean twilioSdkInited;
private static boolean twilioSdkInitInProgress;
private boolean queuedConnect;
private Device device;
private Connection pendingIncomingConnection;
private Connection connection;
private boolean speakerEnabled;
private String lastClientName;
private boolean lastAllowOutgoing;
private boolean lastAllowIncoming;
private IncomingPhone(Context context) {
this.context = context;
}
public void setListeners(LoginListener loginListener,
BasicConnectionListener basicConnectionListener,
BasicDeviceListener basicDeviceListener) {
this.loginListener = loginListener;
this.basicConnectionListener = basicConnectionListener;
this.basicDeviceListener = basicDeviceListener;
}
private void obtainCapabilityToken(String clientName,
boolean allowOutgoing, boolean allowIncoming) {
StringBuilder url = new StringBuilder();
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
DefaultHttpClient httpclient = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory
.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(
httpclient.getParams(), registry);
#SuppressWarnings("unused")
DefaultHttpClient httpClient = new DefaultHttpClient(mgr,
httpclient.getParams());
// Set verifier
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
url.append(AUTH_PHP_SCRIPT);
// This runs asynchronously!
new GetAuthTokenAsyncTask().execute(url.toString());
}
private boolean isCapabilityTokenValid() {
if (device == null || device.getCapabilities() == null)
return false;
long expTime = (Long) device.getCapabilities().get(
Capability.EXPIRATION);
return expTime - System.currentTimeMillis() / 1000 > 0;
}
//
private void updateAudioRoute() {
AudioManager audioManager = (AudioManager) context
.getSystemService(Context.AUDIO_SERVICE);
audioManager.setSpeakerphoneOn(speakerEnabled);
}
public void login(final String clientName, final boolean allowOutgoing,
final boolean allowIncoming) {
if (loginListener != null)
loginListener.onLoginStarted();
this.lastClientName = clientName;
this.lastAllowOutgoing = allowOutgoing;
this.lastAllowIncoming = allowIncoming;
if (!twilioSdkInited) {
if (twilioSdkInitInProgress)
return;
twilioSdkInitInProgress = true;
Twilio.setLogLevel(Log.DEBUG);
Twilio.initialize(context, new Twilio.InitListener() {
#Override
public void onInitialized() {
twilioSdkInited = true;
twilioSdkInitInProgress = false;
obtainCapabilityToken(clientName, allowOutgoing,
allowIncoming);
}
#Override
public void onError(Exception error) {
twilioSdkInitInProgress = false;
if (loginListener != null)
loginListener.onLoginError(error);
}
});
} else {
obtainCapabilityToken(clientName, allowOutgoing, allowIncoming);
}
}
private void reallyLogin(final String capabilityToken) {
try {
if (device == null) {
device = Twilio.createDevice(capabilityToken, this);
Intent intent = new Intent(context, IncomingPhoneActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
device.setIncomingIntent(pendingIntent);
} else
device.updateCapabilityToken(capabilityToken);
if (loginListener != null)
loginListener.onLoginFinished();
if (queuedConnect) {
// If someone called connect() before we finished initializing
// the SDK, let's take care of that here.
connect(null);
queuedConnect = false;
}
} catch (Exception e) {
if (device != null)
device.release();
device = null;
if (loginListener != null)
loginListener.onLoginError(e);
}
}
public void setSpeakerEnabled(boolean speakerEnabled) {
if (speakerEnabled != this.speakerEnabled) {
this.speakerEnabled = speakerEnabled;
updateAudioRoute();
}
}
public void connect(Map<String, String> inParams) {
if (twilioSdkInitInProgress) {
// If someone calls connect() before the SDK is initialized, we'll
// remember
// that fact and try to connect later.
queuedConnect = true;
return;
}
if (!isCapabilityTokenValid())
login(lastClientName, lastAllowOutgoing, lastAllowIncoming);
if (device == null)
return;
if (canMakeOutgoing()) {
disconnect();
connection = device.connect(inParams, this);
if (connection == null && basicConnectionListener != null)
basicConnectionListener
.onConnectionFailedConnecting(new Exception(
"Couldn't create new connection"));
}
}
public void disconnect() {
IncomingPhoneActivity.incomingAlert = null;
if (connection != null) {
connection.disconnect(); // will null out in onDisconnected()
if (basicConnectionListener != null)
basicConnectionListener.onConnectionDisconnecting();
}
}
public void acceptConnection() {
if (pendingIncomingConnection != null) {
if (connection != null)
disconnect();
pendingIncomingConnection.accept();
connection = pendingIncomingConnection;
pendingIncomingConnection = null;
}
}
public void connecta(String phoneNumber) {
Toast.makeText(context, "Calling...", Toast.LENGTH_SHORT).show();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("group_id", "11");
// String capabilityToken;
try {
device = Twilio
.createDevice(decodedString, this /* DeviceListener */);
} catch (Exception e1) {
e1.printStackTrace();
}
try {
device.disconnectAll();
} catch (Exception e) {
e.printStackTrace();
}
connection = device.connect(parameters, this);
if (connection == null) {
Log.w(TAG, "Failed to create new connection");
}
}
public void ignoreIncomingConnection() {
if (pendingIncomingConnection != null) {
pendingIncomingConnection.ignore();
}
}
public boolean isConnected() {
return connection != null
&& connection.getState() == Connection.State.CONNECTED;
}
public Connection.State getConnectionState() {
return connection != null ? connection.getState()
: Connection.State.DISCONNECTED;
}
public boolean hasPendingConnection() {
return pendingIncomingConnection != null;
}
public boolean handleIncomingIntent(Intent intent) {
Device inDevice = intent.getParcelableExtra(Device.EXTRA_DEVICE);
Connection inConnection = intent
.getParcelableExtra(Device.EXTRA_CONNECTION);
if (inDevice == null && inConnection == null)
return false;
intent.removeExtra(Device.EXTRA_DEVICE);
intent.removeExtra(Device.EXTRA_CONNECTION);
if (pendingIncomingConnection != null) {
Log.i(TAG, "A pending connection already exists");
inConnection.ignore();
return false;
}
pendingIncomingConnection = inConnection;
pendingIncomingConnection.setConnectionListener(this);
return true;
}
public boolean canMakeOutgoing() {
if (device == null)
return false;
Map<Capability, Object> caps = device.getCapabilities();
return caps.containsKey(Capability.OUTGOING)
&& (Boolean) caps.get(Capability.OUTGOING);
}
public boolean canAcceptIncoming() {
if (device == null)
return false;
Map<Capability, Object> caps = device.getCapabilities();
return caps.containsKey(Capability.INCOMING)
&& (Boolean) caps.get(Capability.INCOMING);
}
public void setCallMuted(boolean isMuted) {
if (connection != null) {
connection.setMuted(isMuted);
}
}
#Override
/* DeviceListener */
public void onStartListening(Device inDevice) {
if (basicDeviceListener != null)
basicDeviceListener.onDeviceStartedListening();
}
#Override
/* DeviceListener */
public void onStopListening(Device inDevice) {
if (basicDeviceListener != null)
basicDeviceListener.onDeviceStoppedListening(null);
}
#Override
/* DeviceListener */
public void onStopListening(Device inDevice, int inErrorCode,
String inErrorMessage) {
if (basicDeviceListener != null)
basicDeviceListener.onDeviceStoppedListening(new Exception(
inErrorMessage));
}
#Override
/* DeviceListener */
public boolean receivePresenceEvents(Device inDevice) {
return false;
}
#Override
/* DeviceListener */
public void onPresenceChanged(Device inDevice, PresenceEvent inPresenceEvent) {
}
#Override
/* ConnectionListener */
public void onConnecting(Connection inConnection) {
if (basicConnectionListener != null)
basicConnectionListener.onConnectionConnecting();
}
#Override
/* ConnectionListener */
public void onConnected(Connection inConnection) {
updateAudioRoute();
if (basicConnectionListener != null)
basicConnectionListener.onConnectionConnected();
}
#Override
/* ConnectionListener */
public void onDisconnected(Connection inConnection) {
if (inConnection == connection) {
connection = null;
if (basicConnectionListener != null)
basicConnectionListener.onConnectionDisconnected();
} else if (inConnection == pendingIncomingConnection) {
pendingIncomingConnection = null;
if (basicConnectionListener != null)
basicConnectionListener.onIncomingConnectionDisconnected();
}
}
#Override
/* ConnectionListener */
public void onDisconnected(Connection inConnection, int inErrorCode,
String inErrorMessage) {
if (inConnection == connection) {
connection = null;
if (basicConnectionListener != null)
basicConnectionListener
.onConnectionFailedConnecting(new Exception(
inErrorMessage));
}
}
private class GetAuthTokenAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
IncomingPhone.this.reallyLogin(result);
}
#Override
protected String doInBackground(String... params) {
try {
capabilityToken = HttpHelper.httpGet(params[0]);
decodedString = capabilityToken.replace("\"", "");
} catch (Exception e) {
e.printStackTrace();
}
return decodedString;
}
}
}
And the activity which opens after getting incoming call via Service class.
public class IncomingPhoneActivity extends Activity implements LoginListener,
BasicConnectionListener, BasicDeviceListener, View.OnClickListener,
CompoundButton.OnCheckedChangeListener,
RadioGroup.OnCheckedChangeListener {
private static final Handler handler = new Handler();
public IncomingPhone phone;
SharedPreferences login_details;
Vibrator vibrator;
private LinearLayout disconnect_btn;
private LinearLayout mainButton;
private ToggleButton speakerButton;
private ToggleButton muteButton;
private EditText logTextBox;
static AlertDialog incomingAlert;
private EditText outgoingTextBox;
private EditText clientNameTextBox;
private Button capabilitesButton;
private CheckBox incomingCheckBox, outgoingCheckBox;
Button call_btn, dis_call_btn, updateButton;
public static String AUTH_PHP_SCRIPT, rating1, rating2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.call_screen);
Intent intent = getIntent();
Operator_id = intent.getStringExtra("operator_id");
gps = new GPSTracker(IncomingPhoneActivity.this);
if (gps.canGetLocation()) {
latitude = gps.getLatitude();
longitude = gps.getLongitude();
} else {
// gps.showSettingsAlert();
latitude = 0.00;
longitude = 0.00;
}
login_details = getSharedPreferences(LOGIN_DETAILS,
Context.MODE_PRIVATE);
if (login_details.contains("twilio_Id")) {
Twilio_id = login_details.getString("twilio_Id", "");
}
AUTH_PHP_SCRIPT = "http://xxxxxxxxxxxxxx/getGenToken?group_id="
+ Operator_id + "&twilio_id=" + Twilio_id + "&latitude="
+ latitude + "&longitude=" + longitude;
disconnect_btn = (LinearLayout) findViewById(R.id.d_call);
mainButton = (LinearLayout) findViewById(R.id.call);
call_btn = (Button) findViewById(R.id.call_btn);
dis_call_btn = (Button) findViewById(R.id.d_call_btn);
mainButton.setOnClickListener(this);
call_btn.setOnClickListener(this);
dis_call_btn.setOnClickListener(this);
disconnect_btn.setOnClickListener(this);
mainButton.setEnabled(false);
call_btn.setEnabled(false);
speakerButton = (ToggleButton) findViewById(R.id.speaker_btn);
speakerButton.setOnCheckedChangeListener(this);
muteButton = (ToggleButton) findViewById(R.id.mute_btn);
muteButton.setOnCheckedChangeListener(this);
logTextBox = (EditText) findViewById(R.id.log_text_box);
outgoingTextBox = (EditText) findViewById(R.id.outgoing_client);
clientNameTextBox = (EditText) findViewById(R.id.client_name);
clientNameTextBox.setText(DEFAULT_CLIENT_NAME);
capabilitesButton = (Button) findViewById(R.id.capabilites_button);
capabilitesButton.setOnClickListener(this);
outgoingCheckBox = (CheckBox) findViewById(R.id.outgoing);
incomingCheckBox = (CheckBox) findViewById(R.id.incoming);
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (MenuItems.Speaker == true) {
speakerButton.setVisibility(View.VISIBLE);
} else {
speakerButton.setVisibility(View.INVISIBLE);
}
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
phone = IncomingPhone.getInstance(getApplicationContext());
phone.setListeners(this, this, this);
phone.login(DEFAULT_CLIENT_NAME, outgoingCheckBox.isChecked(),
incomingCheckBox.isChecked());
}
private void syncMainButton() {
handler.post(new Runnable() {
public void run() {
if (IncomingPhone.decodedString.length() != 0) {
if (phone.isConnected()) {
switch (phone.getConnectionState()) {
default:
mainButton.setClickable(true);
mainButton.setEnabled(true);
call_btn.setEnabled(true);
mainButton.setVisibility(View.VISIBLE);
disconnect_btn.setVisibility(View.GONE);
disconnect_btn.setClickable(false);
break;
case DISCONNECTED:
mainButton.setVisibility(View.VISIBLE);
disconnect_btn.setVisibility(View.GONE);
disconnect_btn.setClickable(false);
break;
case CONNECTED:
mainButton.setVisibility(View.GONE);
disconnect_btn.setVisibility(View.VISIBLE);
disconnect_btn.setClickable(true);
break;
case CONNECTING:
mainButton.setVisibility(View.GONE);
disconnect_btn.setVisibility(View.VISIBLE);
disconnect_btn.setClickable(true);
break;
}
} else if (phone.hasPendingConnection()) {
mainButton.setClickable(true);
mainButton.setEnabled(true);
call_btn.setEnabled(true);
mainButton.setVisibility(View.VISIBLE);
disconnect_btn.setVisibility(View.GONE);
disconnect_btn.setClickable(false);
} else {
mainButton.setVisibility(View.VISIBLE);
disconnect_btn.setVisibility(View.GONE);
disconnect_btn.setClickable(false);
}
/*
* else { Toast.makeText(getApplicationContext(),
* "TRY AGAIN!", Toast.LENGTH_SHORT).show(); }
*/
}
}
});
}
public void onBackPressed() {
phone.disconnect();
incomingAlert = null;
Intent in = new Intent(IncomingPhoneActivity.this, MenuItems.class);
in.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(in);
finish();
}
class TokenTask extends AsyncTask<Void, Void, Void> {
String message;
JSONObject jsonResponse;
int crash_app;
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... params) {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpGet httppost = new HttpGet(AUTH_PHP_SCRIPT);
try {
HttpResponse response = httpclient.execute(httppost);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
if (entity != null) {
IncomingPhone.capabilityToken = EntityUtils
.toString(entity);
IncomingPhone.decodedString = IncomingPhone.capabilityToken
.replace("\"", "");
}
}
} catch (Exception e) {
crash_app = 5;
message = "Something went wrong. Please try again later.";
return null;
}
return null;
}
#Override
protected void onPostExecute(Void result) {
if (status.equals("success")) {
final Handler handler12 = new Handler();
handler12.postDelayed(new Runnable() {
public void run() {
mainButton.setEnabled(true);
call_btn.setEnabled(true);
mainButton
.setBackgroundResource(R.drawable.light_green_connect);
}
}, 3000);
}
if (status.equals("failure")) {
Toast.makeText(getApplicationContext(), message,
Toast.LENGTH_LONG).show();
// mainButton.setBackgroundColor(Color.parseColor("#4ca64c"));
mainButton.setBackgroundResource(R.drawable.dark_green_connect);
mainButton.setEnabled(false);
call_btn.setEnabled(false);
}
}
}
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
#Override
public void onResume() {
super.onResume();
if (phone.handleIncomingIntent(getIntent())) {
showIncomingAlert();
addStatusMessage(R.string.got_incoming);
if (Utils.isNetworkAvailable(IncomingPhoneActivity.this)) {
syncMainButton();
} else {
Toast.makeText(IncomingPhoneActivity.this,
"No internet connection!!", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (phone != null) {
phone.setListeners(null, null, null);
phone = null;
}
}
#Override
public void onClick(View view) {
if ((view.getId() == R.id.d_call) || (view.getId() == R.id.d_call_btn)) {
phone.disconnect();
incomingAlert = null;
phone.setSpeakerEnabled(false);
phone.setCallMuted(false);
Intent in = new Intent(IncomingPhoneActivity.this, MenuItems.class);
startActivity(in);
finish();
}
if ((view.getId() == R.id.call) || (view.getId() == R.id.call_btn)) {
} else if (view.getId() == R.id.capabilites_button) {
phone.login(clientNameTextBox.getText().toString(),
outgoingCheckBox.isChecked(), incomingCheckBox.isChecked());
}
}
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (group.getId() == R.id.input_select) {
if (checkedId == R.id.input_number) {
outgoingTextBox.setInputType(InputType.TYPE_CLASS_PHONE);
outgoingTextBox.setHint(R.string.outgoing_number);
} else {
outgoingTextBox.setInputType(InputType.TYPE_CLASS_TEXT);
outgoingTextBox.setHint(R.string.outgoing_client);
}
outgoingTextBox.setText("");
}
}
#Override
public void onCheckedChanged(CompoundButton button, boolean isChecked) {
if (button.getId() == R.id.speaker_btn) {
phone.setSpeakerEnabled(isChecked);
} else if (button.getId() == R.id.mute_btn) {
phone.setCallMuted(isChecked);
}
}
private void addStatusMessage(final String message) {
handler.post(new Runnable() {
#Override
public void run() {
logTextBox.append('-' + message + '\n');
}
});
}
private void addStatusMessage(int stringId) {
addStatusMessage(getString(stringId));
}
private void showIncomingAlert() {
handler.post(new Runnable() {
#Override
public void run() {
if (incomingAlert == null) {
notification = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
r = RingtoneManager.getRingtone(getApplicationContext(),
notification);
am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
switch (am.getRingerMode()) {
case AudioManager.RINGER_MODE_SILENT:
r.play();
break;
case AudioManager.RINGER_MODE_VIBRATE:
long pattern[] = { 0, 500, 200, 300, 500 };
vibrator.vibrate(pattern, 0);
break;
case AudioManager.RINGER_MODE_NORMAL:
r.play();
break;
}
incomingAlert = new AlertDialog.Builder(
IncomingPhoneActivity.this)
.setTitle(R.string.incoming_call)
.setCancelable(false)
.setMessage(R.string.incoming_call_message)
.setPositiveButton(R.string.answer,
new DialogInterface.OnClickListener() {
#Override
public void onClick(
DialogInterface dialog,
int which) {
switch (am.getRingerMode()) {
case AudioManager.RINGER_MODE_SILENT:
r.stop();
break;
case AudioManager.RINGER_MODE_VIBRATE:
vibrator.cancel();
break;
case AudioManager.RINGER_MODE_NORMAL:
r.stop();
break;
}
phone.acceptConnection();
disconnect_btn
.setVisibility(View.VISIBLE);
mainButton.setVisibility(View.GONE);
incomingAlert = null;
}
})
.setNegativeButton(R.string.ignore,
new DialogInterface.OnClickListener() {
#Override
public void onClick(
DialogInterface dialog,
int which) {
switch (am.getRingerMode()) {
case AudioManager.RINGER_MODE_SILENT:
r.stop();
break;
case AudioManager.RINGER_MODE_VIBRATE:
vibrator.cancel();
break;
case AudioManager.RINGER_MODE_NORMAL:
r.stop();
break;
}
phone.ignoreIncomingConnection();
incomingAlert = null;
}
})
.setOnCancelListener(
new DialogInterface.OnCancelListener() {
#Override
public void onCancel(
DialogInterface dialog) {
phone.ignoreIncomingConnection();
}
}).create();
incomingAlert.show();
}
}
});
}
private void hideIncomingAlert() {
handler.post(new Runnable() {
#Override
public void run() {
if (incomingAlert != null) {
incomingAlert.dismiss();
incomingAlert = null;
}
}
});
}
#Override
public void onLoginStarted() {
addStatusMessage(R.string.logging_in);
}
#Override
public void onLoginFinished() {
addStatusMessage(phone.canMakeOutgoing() ? R.string.outgoing_ok
: R.string.no_outgoing_capability);
addStatusMessage(phone.canAcceptIncoming() ? R.string.incoming_ok
: R.string.no_incoming_capability);
syncMainButton();
}
#Override
public void onLoginError(Exception error) {
if (error != null)
addStatusMessage(String.format(getString(R.string.login_error_fmt),
error.getLocalizedMessage()));
else
addStatusMessage(R.string.login_error_unknown);
syncMainButton();
}
#Override
public void onIncomingConnectionDisconnected() {
hideIncomingAlert();
addStatusMessage(R.string.incoming_disconnected);
syncMainButton();
}
#Override
public void onConnectionConnecting() {
addStatusMessage(R.string.attempting_to_connect);
syncMainButton();
}
#Override
public void onConnectionConnected() {
addStatusMessage(R.string.connected);
syncMainButton();
}
#Override
public void onConnectionFailedConnecting(Exception error) {
if (error != null)
addStatusMessage(String.format(
getString(R.string.couldnt_establish_outgoing_fmt),
error.getLocalizedMessage()));
else
addStatusMessage(R.string.couldnt_establish_outgoing);
}
#Override
public void onConnectionDisconnecting() {
addStatusMessage(R.string.disconnect_attempt);
syncMainButton();
}
#Override
public void onConnectionDisconnected() {
addStatusMessage(R.string.disconnected);
syncMainButton();
}
#Override
public void onConnectionFailed(Exception error) {
if (error != null)
addStatusMessage(String.format(
getString(R.string.connection_error_fmt),
error.getLocalizedMessage()));
else
addStatusMessage(R.string.connection_error);
syncMainButton();
}
#Override
public void onDeviceStartedListening() {
addStatusMessage(R.string.device_listening);
}
#Override
public void onDeviceStoppedListening(Exception error) {
if (error != null)
addStatusMessage(String.format(
getString(R.string.device_listening_error_fmt),
error.getLocalizedMessage()));
else
addStatusMessage(R.string.device_not_listening);
}
}
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.