Get latitude and longitude from onSuccess(LocationEngineResult result) [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
I get user current location by using override method
public void onSuccess(LocationEngineResult result) {
location = Point.fromLngLat(result.getLastLocation().getLongitude(),result.getLastLocation().getLatitude());
}
but I don't know how to replace the latitude and longitude on variable
private final Point ROUTE_ORIGIN=Point.fromLngLat(location.longitude(),location.latitude());
with the location i get from public void onSuccess(LocationEngineResult result) is there any solution for this?
The app crashed with error
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'double com.mapbox.geojson.Point.longitude()' on a null object reference
Can anyone give me some idea or solution? I tried to find sources but still can't solve it.
public class ArActivity extends BaseActivity implements RouteListener, ProgressChangeListener, OffRouteListener {
private static final String TAG = ArActivity.class.getSimpleName();
// Handles navigation.
private MapboxNavigation mapboxNavigation;
// Fetches route from points.
private RouteFetcher routeFetcher;
private RouteProgress lastRouteProgress;
private PermissionsManager permissionsManager;
private LocationEngine locationEngine;
private LocationEngineCallback<LocationEngineResult> locationCallback;
public Point location;
private boolean visionManagerWasInit = false;
private boolean navigationWasStarted = false;
TextView tvlocation;
// This dummy points will be used to build route. For real world test this needs to be changed to real values for
// source and target location
private final Point ROUTE_ORIGIN=Point.fromLngLat(location.longitude(),location.latitude());
private final Point ROUTE_DESTINATION = Point.fromLngLat(101.769116, 2.923220);
#Override
protected void initViews() {
setContentView(R.layout.activity_ar_navigation);
tvlocation = findViewById(R.id.location);
}
#Override
protected void onPermissionsGranted() {
startVisionManager();
startNavigation();
}
#Override
protected void onStart() {
super.onStart();
startVisionManager();
startNavigation();
}
#Override
protected void onStop() {
super.onStop();
stopVisionManager();
stopNavigation();
}
private void startVisionManager() {
if (allPermissionsGranted() && !visionManagerWasInit) {
// Create and start VisionManager.
VisionManager.create();
VisionManager.setModelPerformanceConfig(new Merged(new On(ModelPerformanceMode.DYNAMIC, ModelPerformanceRate.LOW)));
VisionManager.start();
VisionManager.setVisionEventsListener(new VisionEventsListener() {
#Override
public void onAuthorizationStatusUpdated(#NotNull AuthorizationStatus authorizationStatus) {
}
#Override
public void onFrameSegmentationUpdated(#NotNull FrameSegmentation frameSegmentation) {
}
#Override
public void onFrameDetectionsUpdated(#NotNull FrameDetections frameDetections) {
}
#Override
public void onFrameSignClassificationsUpdated(#NotNull FrameSignClassifications frameSignClassifications) {
}
#Override
public void onRoadDescriptionUpdated(#NotNull RoadDescription roadDescription) {
}
#Override
public void onWorldDescriptionUpdated(#NotNull WorldDescription worldDescription) {
}
#Override
public void onVehicleStateUpdated(#NotNull VehicleState vehicleState) {
}
#Override
public void onCameraUpdated(#NotNull Camera camera) {
}
#Override
public void onCountryUpdated(#NotNull Country country) {
}
#Override
public void onUpdateCompleted() {
}
});
VisionArView visionArView = findViewById(R.id.mapbox_ar_view);
// Create VisionArManager.
VisionArManager.create(VisionManager.INSTANCE);
visionArView.setArManager(VisionArManager.INSTANCE);
visionArView.setFenceVisible(true);
visionManagerWasInit = true;
}
}
private void stopVisionManager() {
if (visionManagerWasInit) {
VisionArManager.destroy();
VisionManager.stop();
VisionManager.destroy();
visionManagerWasInit = false;
}
}
private void startNavigation() {
if (allPermissionsGranted() && !navigationWasStarted) {
// Initialize navigation with your Mapbox access token.
mapboxNavigation = new MapboxNavigation(
this,
getString(R.string.mapbox_access_token),
MapboxNavigationOptions.builder().build()
);
// Initialize route fetcher with your Mapbox access token.
routeFetcher = new RouteFetcher(this, getString(R.string.mapbox_access_token));
routeFetcher.addRouteListener(this);
locationEngine = LocationEngineProvider.getBestLocationEngine(this);
LocationEngineRequest arLocationEngineRequest = new LocationEngineRequest.Builder(0)
.setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
.setFastestInterval(1000)
.build();
locationCallback = new LocationEngineCallback<LocationEngineResult> () {
#Override
public void onSuccess(LocationEngineResult result) {
location = Point.fromLngLat(result.getLastLocation().getLongitude(),result.getLastLocation().getLatitude());
}
#Override
public void onFailure(#NonNull Exception exception) {
}
};
try {
locationEngine.requestLocationUpdates(arLocationEngineRequest, locationCallback, Looper.getMainLooper());
} catch (SecurityException se) {
VisionLogger.Companion.e(TAG, se.toString());
}
initDirectionsRoute();
// Route need to be reestablished if off route happens.
mapboxNavigation.addOffRouteListener(this);
mapboxNavigation.addProgressChangeListener(this);
navigationWasStarted = true;
}
}
private void stopNavigation() {
if (navigationWasStarted) {
locationEngine.removeLocationUpdates(locationCallback);
mapboxNavigation.removeProgressChangeListener(this);
mapboxNavigation.removeOffRouteListener(this);
mapboxNavigation.stopNavigation();
navigationWasStarted = false;
}
}
private void initDirectionsRoute() {
// Get route from predefined points.
NavigationRoute.builder(this)
.accessToken(getString(R.string.mapbox_access_token))
.origin(ROUTE_ORIGIN)
.destination(ROUTE_DESTINATION)
.build()
.getRoute(new Callback<DirectionsResponse>() {
#Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
if (response.body() == null || response.body().routes().isEmpty()) {
return;
}
// Start navigation session with retrieved route.
DirectionsRoute route = response.body().routes().get(0);
mapboxNavigation.startNavigation(route);
// Set route progress.
VisionArManager.setRoute(new Route(
getRoutePoints(route),
route.duration().floatValue(),
"",
""
));
}
#Override
public void onFailure(Call<DirectionsResponse> call, Throwable t) {
}
});
}
#Override
public void onErrorReceived(Throwable throwable) {
if (throwable != null) {
throwable.printStackTrace();
}
mapboxNavigation.stopNavigation();
Toast.makeText(this, "Can not calculate the route requested", Toast.LENGTH_SHORT).show();
}
#Override
public void onResponseReceived(#NotNull DirectionsResponse response, RouteProgress routeProgress) {
mapboxNavigation.stopNavigation();
if (response.routes().isEmpty()) {
Toast.makeText(this, "Can not calculate the route requested", Toast.LENGTH_SHORT).show();
} else {
DirectionsRoute route = response.routes().get(0);
mapboxNavigation.startNavigation(route);
// Set route progress.
VisionArManager.setRoute(new Route(
getRoutePoints(route),
(float) routeProgress.durationRemaining(),
"",
""
));
}
}
#Override
public void onProgressChange(Location location, RouteProgress routeProgress) {
lastRouteProgress = routeProgress;
}
#Override
public void userOffRoute(Location location) {
routeFetcher.findRouteFromRouteProgress(location, lastRouteProgress);
}
private RoutePoint[] getRoutePoints(#NotNull DirectionsRoute route) {
ArrayList<RoutePoint> routePoints = new ArrayList<>();
List<RouteLeg> legs = route.legs();
if (legs != null) {
for (RouteLeg leg : legs) {
List<LegStep> steps = leg.steps();
if (steps != null) {
for (LegStep step : steps) {
RoutePoint point = new RoutePoint((new GeoCoordinate(
step.maneuver().location().latitude(),
step.maneuver().location().longitude()
)), mapToManeuverType(step.maneuver().type()));
routePoints.add(point);
List<Point> geometryPoints = buildStepPointsFromGeometry(step.geometry());
for (Point geometryPoint : geometryPoints) {
point = new RoutePoint((new GeoCoordinate(
geometryPoint.latitude(),
geometryPoint.longitude()
)), ManeuverType.None);
routePoints.add(point);
}
}
}
}
}
return routePoints.toArray(new RoutePoint[0]);
}
private List<Point> buildStepPointsFromGeometry(String geometry) {
return PolylineUtils.decode(geometry, Constants.PRECISION_6);
}
private ManeuverType mapToManeuverType(#Nullable String maneuver) {
if (maneuver == null) {
return ManeuverType.None;
}
switch (maneuver) {
case "turn":
return ManeuverType.Turn;
case "depart":
return ManeuverType.Depart;
case "arrive":
return ManeuverType.Arrive;
case "merge":
return ManeuverType.Merge;
case "on ramp":
return ManeuverType.OnRamp;
case "off ramp":
return ManeuverType.OffRamp;
case "fork":
return ManeuverType.Fork;
case "roundabout":
return ManeuverType.Roundabout;
case "exit roundabout":
return ManeuverType.RoundaboutExit;
case "end of road":
return ManeuverType.EndOfRoad;
case "new name":
return ManeuverType.NewName;
case "continue":
return ManeuverType.Continue;
case "rotary":
return ManeuverType.Rotary;
case "roundabout turn":
return ManeuverType.RoundaboutTurn;
case "notification":
return ManeuverType.Notification;
case "exit rotary":
return ManeuverType.RotaryExit;
default:
return ManeuverType.None;
}
}

At the point of instantiating this line (i.e. when the class loads):
private final Point ROUTE_ORIGIN=Point.fromLngLat(location.longitude(),location.latitude());
The location variable you are using is set to nothing:
public Point location;
Aka, it is null and you are getting a NullPointerException.
You should either not try to use the location object until it is instantiated, setting your routeOrigin later on. Or change the ROUTE_ORIGIN to use a static location, the same way you have for ROUTE_DESTINATION.

Related

Flutter E/EventChannel : Failed to open event stream System services not available to Activities before onCreate()

I can't solve this problem. I want to write a flutter plugin for connecting to scales via bluetooth, but the scales sdk It's being used through the activity page, so I tried to find information about the activity usage in the flutter plugin, so I tried to run it. ActivityAware But I can't run the SDK and I can't pass values from extend class of sdk into EventChanel and can't send back to stream flutter.
this Logcat Error
2022-09-03 01:35:18.966 7973-7973/com.example.releep_scale_connect_example E/EventChannel#scan_releep_scale: Failed to open event stream
java.lang.IllegalStateException: System services not available to Activities before onCreate()
at android.app.Activity.getSystemService(Activity.java:6916)
at aicare.net.cn.iweightlibrary.bleprofile.BleProfileServiceReadyActivity.isBLEEnabled(BleProfileServiceReadyActivity.java:299)
at aicare.net.cn.iweightlibrary.bleprofile.BleProfileServiceReadyActivity.startScan(BleProfileServiceReadyActivity.java:329)
at com.example.releep_scale_connect.ReleepScaleConnectPlugin.onListen(ReleepScaleConnectPlugin.java:156)
at io.flutter.plugin.common.EventChannel$IncomingStreamRequestHandler.onListen(EventChannel.java:218)
at io.flutter.plugin.common.EventChannel$IncomingStreamRequestHandler.onMessage(EventChannel.java:197)
at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:178)
at io.flutter.embedding.engine.dart.DartMessenger.lambda$handleMessageFromDart$0$DartMessenger(DartMessenger.java:206)
at io.flutter.embedding.engine.dart.-$$Lambda$DartMessenger$6ZD1MYkhaLxyPjtoFDxe45u43DI.run(Unknown Source:12)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:8051)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:620)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1011)
2022-09-03 01:35:18.978 7973-7973/com.example.releep_scale_connect_example W/Looper: PerfMonitor longMsg : seq=135 plan=01:35:17.167 late=0ms wall=1800ms running=24ms runnable=1ms h=android.os.Handler c=io.flutter.embedding.engine.dart.-$$Lambda$DartMessenger$6ZD1MYkhaLxyPjtoFDxe45u43DI procState=2
this my plugin (ReleepScaleConnectPlugin.java)
I want this SDK to be in flutter plugin format.
this github SDK : https://github.com/evanwork1234/AiFitSDK
public class ReleepScaleConnectPlugin extends BleProfileServiceReadyActivity implements FlutterPlugin, EventChannel.StreamHandler, MethodCallHandler, ActivityAware {
private FlutterActivity activity;
private MethodChannel channel;
private EventChannel stream_chanel;
private DeviceDialog devicesDialog;
private BinaryMessenger binaryMessenger;
private String[] permissionArray = new String[] {
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_NETWORK_STATE
};
#Override
public void onAttachedToEngine(#NonNull FlutterPluginBinding flutterPluginBinding) {
binaryMessenger = flutterPluginBinding.getBinaryMessenger();
}
#Override
public void onMethodCall(#NonNull MethodCall call, #NonNull Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else {
result.notImplemented();
}
}
#Override
public void onDetachedFromEngine(#NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
ArrayList listVal = new ArrayList();
private Gson gson = new Gson();
#Override
public void onListen(Object arguments, EventChannel.EventSink events) {
if (arguments.equals("scan")) {
// devicesDialog.startScan();
startScan();
String json = gson.toJson(listVal);
events.success(json);
}
}
#Override
public void onCancel(Object arguments) {
}
#Override
protected void onError(String s, int i) {
L.e("TAG", "Message = " + s + " errCode = " + i);
// showInfo(getString(R.string.state_error, errMsg, errCode), true);
}
#Override
protected void onGetWeightData(WeightData weightData) {
}
#Override
protected void onGetResult(int i, String s) {
}
#Override
protected void onServiceBinded(WBYService.WBYBinder wbyBinder) {
}
#Override
protected void onServiceUnbinded() {
}
#Override
protected void getAicareDevice(BroadData broadData) {
if (broadData != null) {
L.e("TAG", broadData.toString());
listVal.add(broadData.toString());
}
}
private void startLeScan() {
startScan();
}
private void stopLeScan() {
stopScan();
}
#Override
public void onAttachedToActivity(#NonNull #NotNull ActivityPluginBinding binding) {
L.e("TAG", "onAttachedToActivity");
activity = (FlutterActivity) binding.getActivity();
AiFitSDK.getInstance().init (activity);
channel = new MethodChannel(binaryMessenger, "releep_scale_connect");
channel.setMethodCallHandler(this);
stream_chanel = new EventChannel(binaryMessenger, "scan_releep_scale");
stream_chanel.setStreamHandler(this);
boolean backBoolean = PermissionUtils.checkPermissionArray(activity.getContext(), permissionArray, 3);
// initPermissions();
// Judge whether Bluetooth is on, if you need to change the style, you can do it yourself
if (!isBLEEnabled()) {
showBLEDialog();
}
//startScan();
// devicesDialog = new DeviceDialog(activity.getContext(), this);
}
#Override
public void onDetachedFromActivityForConfigChanges() {
L.e("TAG", "onDetachedFromActivityForConfigChanges");
}
#Override
public void onReattachedToActivityForConfigChanges(#NonNull #NotNull ActivityPluginBinding binding) {
L.e("TAG", "onReattachedToActivityForConfigChanges");
}
#Override
public void onDetachedFromActivity() {
L.e("TAG", "onDetachedFromActivity");
}
}
I want these override methods to be able to pass values back to flutter.
#Override
protected void onGetWeightData(WeightData weightData) {
}
#Override
protected void onGetResult(int i, String s) {
}
#Override
protected void onGetFatData(boolean b, BodyFatData bodyFatData) {
}

LiveData isn't being observed properly (gets null) when using Android Pagination Library

I am trying to update the UI depending on whether the data is being loaded or has loaded but it is not working properly. I am using enum class for different states.
Initially the error was
Attempt to invoke virtual method 'void androidx.lifecycle.LiveData.observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer)' on a null object reference
Then I passed an empty new MutableLiveData()<>. Now, it doesn't crashes the application, however, the getDataStatus() observer isn't working correctly. Kindly look at my implementations and see if they are right.
DataSource
public class ArticlesDataSource extends PageKeyedDataSource<Integer, NewsItem> {
private static final int FIRST_PAGE = 1;
private static final String TAG = "ArticlesDataSource";
public static final String SORT_ORDER = "publishedAt";
public static final String LANGUAGE = "en";
public static final String API_KEY = Utils.API_KEY;
public static final int PAGE_SIZE = 10;
private String mKeyword;
private MutableLiveData<DataStatus> dataStatusMutableLiveData = new MutableLiveData<>();
public ArticlesDataSource(String keyword) {
mKeyword = keyword;
dataStatusMutableLiveData = new MutableLiveData<>();
}
public MutableLiveData<DataStatus> getDataStatusMutableLiveData() {
return dataStatusMutableLiveData;
}
#Override
public void loadInitial(#NonNull LoadInitialParams<Integer> params, #NonNull LoadInitialCallback<Integer, NewsItem> callback) {
dataStatusMutableLiveData.postValue(DataStatus.LOADING);
NewsAPI newsAPI = ServiceGenerator.createService(NewsAPI.class);
Call<RootJsonData> call = newsAPI.searchArticlesByKeyWord(mKeyword, SORT_ORDER, LANGUAGE, API_KEY, FIRST_PAGE, PAGE_SIZE);
call.enqueue(new Callback<RootJsonData>() {
#Override
public void onResponse(Call<RootJsonData> call, Response<RootJsonData> response) {
if (response.body() != null) {
callback.onResult(response.body().getNewsItems(), null, FIRST_PAGE + 1);
dataStatusMutableLiveData.postValue(DataStatus.LOADED);
}
}
#Override
public void onFailure(Call<RootJsonData> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.getMessage());
dataStatusMutableLiveData.postValue(DataStatus.ERROR);
}
});
}
#Override
public void loadBefore(#NonNull LoadParams<Integer> params, #NonNull LoadCallback<Integer, NewsItem> callback) {
NewsAPI newsAPI = ServiceGenerator.createService(NewsAPI.class);
Call<RootJsonData> call = newsAPI.searchArticlesByKeyWord(mKeyword, SORT_ORDER, LANGUAGE, API_KEY, FIRST_PAGE, PAGE_SIZE);
call.enqueue(new Callback<RootJsonData>() {
#Override
public void onResponse(Call<RootJsonData> call, Response<RootJsonData> response) {
// if the current page is greater than one
// we are decrementing the page number
// else there is no previous page
Integer adjacentKey = (params.key > 1) ? params.key - 1 : null;
if (response.body() != null) {
// passing the loaded data
// and the previous page key
callback.onResult(response.body().getNewsItems(), adjacentKey);
}
}
#Override
public void onFailure(Call<RootJsonData> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.getMessage());
}
});
}
#Override
public void loadAfter(#NonNull LoadParams<Integer> params, #NonNull LoadCallback<Integer, NewsItem> callback) {
NewsAPI newsAPI = ServiceGenerator.createService(NewsAPI.class);
Call<RootJsonData> call = newsAPI.searchArticlesByKeyWord(mKeyword, SORT_ORDER, LANGUAGE, API_KEY, params.key, PAGE_SIZE);
call.enqueue(new Callback<RootJsonData>() {
#Override
public void onResponse(Call<RootJsonData> call, Response<RootJsonData> response) {
dataStatusMutableLiveData.postValue(DataStatus.LOADED);
if (response.code() == 429) {
// no more results
List<NewsItem> emptyList = new ArrayList<>();
callback.onResult(emptyList, null);
}
if (response.body() != null) {
// if the response has next page
// incrementing the next page number
Integer key = params.key + 1;
// passing the loaded data and next page value
if (!response.body().getNewsItems().isEmpty()) {
callback.onResult(response.body().getNewsItems(), key);
}
}
}
#Override
public void onFailure(Call<RootJsonData> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.getMessage());
dataStatusMutableLiveData.postValue(DataStatus.ERROR);
}
});
}
}
DataSourceFactory
public class ArticlesDataSourceFactory extends DataSource.Factory {
private final MutableLiveData<ArticlesDataSource> itemLiveDataSource;
private String mQuery;
private final LiveData<DataStatus> dataStatusLiveData = Transformations.switchMap(itemLiveDataSource, (itemDataSource) -> {
return itemDataSource.getDataStatusMutableLiveData();
});
public ArticlesDataSourceFactory() {
mQuery = "news";
itemLiveDataSource = new MutableLiveData<>();
}
#Override
public DataSource<Integer, NewsItem> create() {
ArticlesDataSource itemDataSource = new ArticlesDataSource(mQuery);
itemLiveDataSource.postValue(itemDataSource);
// dataStatusMutableLiveData = itemDataSource.getDataStatusMutableLiveData();
return itemDataSource;
}
public MutableLiveData<ArticlesDataSource> getArticlesLiveDataSource() {
return itemLiveDataSource;
}
public void setQuery(String query) {
mQuery = query;
}
public MutableLiveData<DataStatus> getDataStatusMutableLiveData() {
return dataStatusMutableLiveData;
}
public void setDataStatusMutableLiveData(DataStatus dataStatus){
dataStatusMutableLiveData.postValue(dataStatus);
}
public LiveData<DataStatus> getDataStatusLiveData() {
return dataStatusLiveData;
}
}
ViewModel
public class ArticlesViewModel extends ViewModel {
public LiveData<PagedList<NewsItem>> itemPagedList;
private MutableLiveData<ArticlesDataSource> liveDataSource;
private ArticlesDataSourceFactory articlesDataSourceFactory;
private LiveData dataStatus = new MutableLiveData<>();
public ArticlesViewModel() {
articlesDataSourceFactory = new ArticlesDataSourceFactory();
liveDataSource = articlesDataSourceFactory.getArticlesLiveDataSource();
dataStatus = articlesDataSourceFactory.getDataStatusMutableLiveData();
PagedList.Config pagedListConfig =
(new PagedList.Config.Builder())
.setEnablePlaceholders(false)
.setPageSize(10).build();
itemPagedList = (new LivePagedListBuilder(articlesDataSourceFactory, pagedListConfig)).build();
}
public void setKeyword(String query) {
if (query.equals("") || query.length() == 0)
articlesDataSourceFactory.setDataStatusMutableLiveData(DataStatus.EMPTY);
else {
articlesDataSourceFactory.setQuery(query);
refreshData();
}
}
void refreshData() {
if (itemPagedList.getValue() != null) {
itemPagedList.getValue().getDataSource().invalidate();
}
}
public LiveData<DataStatus> getDataStatus() {
return dataStatus;
}
}
Fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_articles, container, false);
mContext = getActivity();
progressBar = rootView.findViewById(R.id.progress_circular);
emptyStateTextView = rootView.findViewById(R.id.empty_view);
swipeRefreshLayout = rootView.findViewById(R.id.swipe_refresh);
textViewTitle = rootView.findViewById(R.id.text_view_top_headlines);
recyclerView = rootView.findViewById(R.id.recycler_view);
if (savedInstanceState != null) {
keyword = savedInstanceState.getString("keyword");
}
initEmptyRecyclerView();
articlesViewModel = ViewModelProviders.of(this).get(ArticlesViewModel.class);
articlesViewModel.itemPagedList.observe(getViewLifecycleOwner(), new Observer<PagedList<NewsItem>>() {
#Override
public void onChanged(PagedList<NewsItem> newsItems) {
adapter.submitList(newsItems);
// TODO: Handle UI changes
// handleUIChanges(newsItems);
}
});
articlesViewModel.getDataStatus().observe(getViewLifecycleOwner(), new Observer<DataStatus>() {
#Override
public void onChanged(DataStatus dataStatus) {
switch (dataStatus) {
case LOADED:
progressBar.setVisibility(View.GONE);
emptyStateTextView.setVisibility(View.INVISIBLE);
swipeRefreshLayout.setRefreshing(false);
textViewTitle.setVisibility(View.VISIBLE);
break;
case LOADING:
progressBar.setVisibility(View.VISIBLE);
swipeRefreshLayout.setRefreshing(true);
textViewTitle.setVisibility(View.INVISIBLE);
emptyStateTextView.setVisibility(View.INVISIBLE);
break;
case EMPTY:
progressBar.setVisibility(View.GONE);
swipeRefreshLayout.setRefreshing(false);
textViewTitle.setVisibility(View.INVISIBLE);
emptyStateTextView.setVisibility(View.VISIBLE);
emptyStateTextView.setText(R.string.no_news_found);
break;
case ERROR:
progressBar.setVisibility(View.GONE);
swipeRefreshLayout.setRefreshing(false);
textViewTitle.setVisibility(View.INVISIBLE);
emptyStateTextView.setVisibility(View.VISIBLE);
emptyStateTextView.setText(R.string.no_internet_connection);
break;
}
}
});
swipeRefreshLayout.setOnRefreshListener(() -> {
articlesViewModel.setKeyword(keyword);
});
setHasOptionsMenu(true);
return rootView;
}
DataStatus
public enum DataStatus {
ERROR,
LOADING,
LOADED,
EMPTY
}
When you call invalidate(), a new datasource will be created by the factory. However, you are directly exposing the data status liveData of the "current" created datasource, without taking into consideration that more will be created in the future.
The solution is to store the current data source in the factory in a MutableLiveData, and expose the "most recent current data status" using switchMap.
public class ArticlesDataSourceFactory extends DataSource.Factory {
private final MutableLiveData<ArticlesDataSource> itemLiveDataSource = new MutableLiveData<>();
private String mQuery = "news";
private final LiveData<DataStatus> dataStatusLiveData = Transformations.switchMap(itemLiveDataSource, (itemDataSource) -> {
return itemDataSource.getDataStatusMutableLiveData();
});
public ArticlesDataSourceFactory() {
}
#Override
public DataSource<Integer, NewsItem> create() {
ArticlesDataSource itemDataSource = new ArticlesDataSource(mQuery);
itemLiveDataSource.postValue(itemDataSource);
...
public LiveData<DataStatus> getDataStatusLiveData() {
return dataStatusLiveData;
}

variable return null after method finished

im trying to make a function that translate a text and print the result. im using firebasetranslator.
by debugging, the app starts but the textbox is empty. trying to put a marker on
private void setRisultato(String string){
this.risultato = string;
}
I see that the translated text is correctly assigned to the result variable.
but if I put the marker up
public String getRisultato(){
return risultato;
}
I see what result is null (not empty), can someone explain me why?
UPDATE:
Traduttore.java
import android.app.Activity;
import androidx.annotation.NonNull;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.ml.common.modeldownload.FirebaseModelDownloadConditions;
import com.google.firebase.ml.naturallanguage.FirebaseNaturalLanguage;
import com.google.firebase.ml.naturallanguage.translate.FirebaseTranslateLanguage;
import com.google.firebase.ml.naturallanguage.translate.FirebaseTranslator;
import com.google.firebase.ml.naturallanguage.translate.FirebaseTranslatorOptions;
public class Traduttore extends Activity {
private static String text1;
public interface callbacktranslate {
void onCallback(String risultato);
}
public void traduci(String textblock, final callbacktranslate callback){
//clear string and start translate
String blocktext = textblock.replaceAll("\n"," ");
String blocktext2 = blocktext.replaceAll("\\.","");
String blocktext3 = blocktext2.toUpperCase();
text1 = blocktext3;
downloadTranslatorAndTranslate(callback);
}
public void translateText(FirebaseTranslator langTranslator, final callbacktranslate callback) {
//translate source text to english
langTranslator.translate(text1).addOnSuccessListener(
new OnSuccessListener<String>() {
#Override
public void onSuccess(#NonNull String translatedText) {
//make variable all uppercase and save it
String blocktext4 = translatedText.toUpperCase();
callback.onCallback(blocktext4);
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
}
});
}
public void downloadTranslatorAndTranslate(final callbacktranslate callback) {
int sourceLanguage = 11; //language source(en=11)
//create translator for source and target languages
FirebaseTranslatorOptions options =
new FirebaseTranslatorOptions.Builder()
.setSourceLanguage(sourceLanguage)
.setTargetLanguage(FirebaseTranslateLanguage.IT)
.build();
final FirebaseTranslator langTranslator =
FirebaseNaturalLanguage.getInstance().getTranslator(options);
//download language models if needed
FirebaseModelDownloadConditions conditions = new FirebaseModelDownloadConditions.Builder()
.build();
langTranslator.downloadModelIfNeeded(conditions)
.addOnSuccessListener(
new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void v) {
translateText(langTranslator,callback);
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
}
});
}
}
method in MainActivity.java:
public ConstraintLayout vpp;
public TextView[] textViewArray = new TextView[500];
public int i;
public void StartReadImage(){
FirebaseVisionImage image2 = FirebaseVisionImage.fromBitmap(resizedBitmap);
FirebaseVisionTextRecognizer textRecognizer2 = FirebaseVision.getInstance()
.getOnDeviceTextRecognizer();
final Task<FirebaseVisionText> result2 =
textRecognizer2.processImage(image2)
.addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() {
#Override
public void onSuccess(FirebaseVisionText firebaseVisionText) {
// Task completed successfully
i = 0;
resultText = firebaseVisionText.getText();
for (FirebaseVisionText.TextBlock block: firebaseVisionText.getTextBlocks()) {
String blockText = block.getText();
Float blockConfidence = block.getConfidence();
List<RecognizedLanguage> blockLanguages = block.getRecognizedLanguages();
final Point[] blockCornerPoints = block.getCornerPoints();
final Rect blockFrame = block.getBoundingBox();
traduttore.traduci(blockText, new Traduttore.callbacktranslate() {
#Override
public void onCallback(String result) {
createCover(blockCornerPoints, blockFrame, result, i);
i++;
}
});
}
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Task failed with an exception
}
});
}
public void createCover(Point[] CornerPoint,Rect blockFrame,String blockText, int i){
textViewArray[i] = new TextView(context);
textViewArray[i].setTextSize(9);
textViewArray[i].setGravity(Gravity.CENTER);
textViewArray[i].setTextColor(Color.BLACK);
textViewArray[i].setBackgroundColor(Color.rgb(225, 225, 225));
textViewArray[i].setHeight(blockFrame.height());
textViewArray[i].setWidth(blockFrame.width());
textViewArray[i].setX(CornerPoint[0].x);
textViewArray[i].setY(CornerPoint[0].y);
textViewArray[i].setText(blockText);
vpp.addView(textViewArray[i]);
}
You'll need to set the callback somewhere, and in order to do that, you'll need to add it a few places, and pass it on appropriately
traduci(String textblock, final Callback callback)
downloadTranslatorAndTranslate(final Callback callback)
translateText(FirebaseTranslator langTranslator, final Callback callback)
From there, you need to add the callback to the Activity method call, and that method should be void since the callback comes later from when the method actually returns
public void Traduciblocco(String abc){
traduttore.traduci(abc, new Callback() {
#Override
public void onCallback(String result) {
// resultTxt.setText(result);
}
});
}

Android MIDI Threading InteruptedException - Aftertouch Messages

Trying to run MIDI on my Android app. I'm following the midisuite example to configure my app and it works fine with the exception of aftertouch. Whenever I try to trigger aftertouch, I run into a threading exception type
InteruptedException. How should I prevent this threading issue? My knowledge on multithreading isn't the best or else I would've figured this out already. All I can really tell right now is that the message is sending too fast and the thread hasn't woken up yet from its sleep call.
I followed the github repo with my code as follows:
MidiReceiver subclass:
#TargetApi(Build.VERSION_CODES.M)
public class MidiEngine extends MidiReceiver {
public AudioActivity activity;
private MidiEventScheduler eventScheduler;
private MidiFramer midiFramer;
private MidiReceiver midiReceiver = new MyReceiver();
private Thread mThread;
private boolean go;
private int mProgram;
public MidiEngine() {
this(new AudioActivity());
}
public MidiEngine(AudioActivity activity) {
this.activity = activity;
midiReceiver = new MyReceiver();
midiFramer = new MidiFramer(midiReceiver);
}
public AudioActivity getActivity() {
return this.activity;
}
/* This will be called when MIDI data arrives. */
#Override
public void onSend(byte[] data, int offset, int count, long timestamp)
throws IOException {
if (eventScheduler != null) {
if (!MidiConstants.isAllActiveSensing(data, offset, count)) {
eventScheduler.getReceiver().send(data, offset, count,
timestamp);
}
}
}
// Custom Listener to send to correct methods
private class MyReceiver extends MidiReceiver {
#Override
public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
byte command = (byte)(msg[0] & MidiConstants.STATUS_COMMAND_MASK);
int channel = (byte)(msg[0] & MidiConstants.STATUS_CHANNEL_MASK);
switch (command) {
case MidiConstants.STATUS_NOTE_ON:
activity.keyDown(i, msg[1], msg[2]);
break;
case MidiConstants.STATUS_NOTE_OFF:
activity.keyUp(channel, msg[1]);
break;
case MidiConstants.STATUS_POLYPHONIC_AFTERTOUCH:
activity.keyDown(channel, msg[1], msg[2]);
break;
case MidiConstants.STATUS_PITCH_BEND:
activity.pitchBendAction(channel, (msg[2] << 7) + msg[1]);
break;
case MidiConstants.STATUS_CONTROL_CHANGE:
activity.ccAction(channel, msg[1], msg[2]);
break;
case MidiConstants.STATUS_PROGRAM_CHANGE:
mProgram = msg[1];
break;
default:
break;
}
}
}
class MyRunnable implements Runnable {
#Override
public void run() {
do {
try {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
processMidiEvents();
}
catch (Exception e) {
Log.e("Java", "SynthEngine background thread exception.", e);
}
}
});
Thread.sleep(100);
}
catch (InterruptedException e) {
Log.e("Java", "Threading exception", e);
}
}
while (go);
}
}
/**
* #throws IOException
*
*/
private void processMidiEvents() throws IOException {
long now = System.nanoTime();
MidiEventScheduler.MidiEvent event = (MidiEventScheduler.MidiEvent) eventScheduler.getNextEvent(now);
while (event != null) {
midiFramer.send(event.data, 0, event.count, event.getTimestamp());
eventScheduler.addEventToPool(event);
event = (MidiEventScheduler.MidiEvent) eventScheduler.getNextEvent(now);
}
}
public void start() {
stop();
go = true;
mThread = new Thread(new MyRunnable());
mThread.setPriority(6);
eventScheduler = new MidiEventScheduler();
mThread.start();
}
public void stop() {
go = false;
if (mThread != null) {
try {
mThread.interrupt();
mThread.join(500);
}
catch (Exception e) {
}
mThread = null;
eventScheduler = null;
}
}
}
Stack Trace Error (line 154 refers to the Thread.sleep part in my custom Runnable class):
Java: Threading exception
java.lang.InterruptedException
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:1031)
at java.lang.Thread.sleep(Thread.java:985)
at com.rfoo.midiapp.communication.MidiEngineInput$MyRunnable.run(MidiEngineInput.java:154)
at java.lang.Thread.run(Thread.java:818)
Thanks!
EDIT: Thread start
Midi Device Service subclass (thread will start whenever a device has connected or disconnected).
#TargetApi(Build.VERSION_CODES.M)
public class MidiSynthDeviceService extends MidiDeviceService {
private static final String TAG = "MidiSynthDeviceService";
private boolean midiStarted = false;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
AudioActivity.midiEngine.stop();
super.onDestroy();
}
#Override
// Declare the receivers associated with your input ports.
public MidiReceiver[] onGetInputPortReceivers() {
return new MidiReceiver[] { AudioActivity.midiEngine };
}
/**
* This will get called when clients connect or disconnect.
* You can use it to turn on your synth only when needed.
*/
#Override
public void onDeviceStatusChanged(MidiDeviceStatus status) {
if (status.isInputPortOpen(0) && !midiStarted) {
AudioActivity.midiEngine.start();
midiStarted = true;
} else if (!status.isInputPortOpen(0) && midiStarted){
AudioActivity.midiEngine.stop();
midiStarted = false;
}
}
}
Activity class:
public class AudioActivity extends AppCompatActivity {
private Thread thread;
public static MidiEngine midiEngine;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Layout inits
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Setup MIDI:
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI)) {
Toast.makeText(this, "MIDI not supported!", Toast.LENGTH_LONG).show();
}
else {
midiEngine = new MidiEngine(this);
setupMidi();
}
// Setup audio thread:
if (thread == null) {
thread = new Thread() {
public void run() {
setPriority(Thread.MAX_PRIORITY);
// Runs an Open SL audio thread (C++)
// This generates a waveform.
// AudioEngine is a wrapper class connecting C++ to Java
AudioEngine.runProcess();
}
}
}
}
public void setupMidi() {
if (activity == null) activity = (AudioActivity) getContext();
mMidiManager = (MidiManager) activity.getSystemService(AudioActivity.MIDI_SERVICE);
if (mMidiManager == null) {
Toast.makeText(activity, "MidiManager is null!", Toast.LENGTH_LONG).show();
return;
}
// Get Device Info
MidiDeviceInfo deviceInfo = MidiTools.findDevice(mMidiManager, "RFOO", "AudioApp");
// MIDI Input
portIndex = 0;
inputPortSelector = new MidiOutputPortConnectionSelector(mMidiManager, activity, R.id
.inputListView, deviceInfo, portIndex);
inputPortSelector.setConnectedListener(new MyPortsConnectedListener());
midi_ch_input = 0;
midi_ch_output = 0;
}
// Bunch of UI code here....
}

RxJava: how to turn a complicated if statement into a reactive stream?

I am implementing an app introduction and waiver that should appear before the user can access the MainActivity of my Android app. If the user has not accepted the waiver or gone through the app introduction, then my IntroNavigator kicks them back to those activities.
How can I rxify my redirectIfNecessary() method in a more functional manner, instead of the imperative approach I implemented below.
IntroNavigatorImpl.java
public class IntroNavigatorImpl implements IntroNavigator {
WeakReference<Activity> activityWeakReference;
CloudPrefsRepo cloudPrefsRepo;
public IntroNavigatorImpl(Activity activity, CloudPrefsRepo cloudPrefsRepo) {
this.activityWeakReference = new WeakReference<>(activity);
this.cloudPrefsRepo = cloudPrefsRepo;
}
#Override
public void redirectIfNecessary() {
final boolean shouldShowAppIntro = cloudPrefsRepo.shouldShowAppIntro()
.toObservable().toBlocking().first();
final boolean shouldShowWaiver = cloudPrefsRepo.shouldShowWaiver()
.toObservable().toBlocking().first();
if (shouldShowAppIntro) {
showAppIntro();
finishActivity();
} else if (shouldShowWaiver) {
showWaiver();
finishActivity();
} else {
//do nothing
}
}
#Override
public void showWaiver() {
//launch waiver activity
}
#Override
public void showAppIntro() {
//launch app intro activity
}
public void finishActivity() {
if (activityWeakReference.get() != null) {
activityWeakReference.get().finish();
}
}
}
CloudPrefsRepo.java
public interface
/**
* Whether to show the app intro.
*/
Single<Boolean> shouldShowAppIntro();
/**
* Whether to show the waiver. If the user has already
* accepted this waiver, then it shouldn't be shown.
*/
Single<Boolean> shouldShowWaiver();
Edit Based on comment:
It's not the prettiest (I'm leaning towards there not being a good reactive way to do this)
final Action0 showInfoAction = new Action0() {
#Override
public void call() {
showAppIntro();
finishActivity();
}
};
final Action0 showWaiverAction = new Action0() {
#Override
public void call() {
showWaiver();
finishActivity();
}
};
final Action0 blankAction = new Action0() {
#Override
public void call() {
}
};
Observable.zip(shouldShowInfo, shouldShowWaiver, new Func2<Boolean, Boolean, Action0>() {
#Override
public Action0 call(Boolean shoudlShowInfo, Boolean shouldShowWaiver) {
if (shoudlShowInfo) {
return showInfoAction;
} else if (shouldShowWaiver) {
return showWaiverAction;
} else {
return blankAction;
}
}
}).subscribe(new Action1<Action0>() {
#Override
public void call(Action0 action0) {
action0.call();
}
});

Categories