I’m using the code given here.
I put those code blocks as classes in my project’s util package. And then in the main activity class I wrote this..
class MenuActivity {
// Variable declaration
private final CompositeSubscription mConnectionSubscription = new CompositeSubscription();
#Override
protected void onCreate(Bundle savedInstanceState) {
// Some initialisation of UI elements done here
mConnectionSubscription.add(AppObservable.bindActivity(this, NetworkUtils.observe(this)).subscribe(new Action1<NetworkUtils.State>() {
#Override
public void call(NetworkUtils.State state) {
if(state == NetworkUtils.State.NOT_CONNECTED)
Timber.i("Connection lost");
else
Timber.i("Connected");
}
}));
}
My goal is to monitor the changes and change a variable MyApp.isConnected defined in the MyApp class statically whenever the network changes to true false. Help would be appreciated. Thank you 😄
You asked me for an answer in another thread. I'm answering late, because I needed some time to develop and test solution, which I find good enough.
I've recently created new project called ReactiveNetwork.
It's open-source and available at: https://github.com/pwittchen/ReactiveNetwork.
You can add the following dependency to your build.gradle file:
dependencies {
compile 'com.github.pwittchen:reactivenetwork:x.y.z'
}
Then, you can replace x.y.z with the latest version number.
After that, you can use library in the following way:
ReactiveNetwork.observeNetworkConnectivity(context)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<ConnectivityStatus>() {
#Override public void call(Connectivity connectivity) {
if(connectivity.getState() == NetworkInfo.State.DISCONNECTED) {
Timber.i("Connection lost");
} else if(connectivity.getState() == NetworkInfo.State.CONNECTED) {
Timber.i("Connected");
}
}
});
You can also use filter(...) method from RxJava if you want to react only on a single type of event.
You can create a subscription in onResume() method and then unsubscribe it in onPause() method inside Activity.
You can find more examples of usage and sample app on the website of the project on GitHub.
Moreover, you can read about NetworkInfo.State enum from Android API, which is now used by the library.
Try to use rxnetwork-android:
public class MainActivity extends AppCompatActivity{
private Subscription sendStateSubscription;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Observable<RxNetwork.State> sendStateStream =
RxNetwork.stream(this);
sendStateSubscription = AppObservable.bindActivity(
this, sendStateStream
).subscribe(new Action1<RxNetwork.State>() {
#Override public void call(RxNetwork.State state) {
if(state == RxNetwork.State.NOT_CONNECTED)
Timber.i("Connection lost");
else
Timber.i("Connected");
}
});
}
#Override protected void onDestroy() {
sendStateSubscription.unsubscribe();
sendStateSubscription = null;
super.onDestroy();
}
}
Related
Good day! i'm having an issue with the qr code scanner in android marshmallow and nougat using the library that i have added as dependency in my project the camera shows white screen. Code runs perfectly in lollipop and kitkat. Please let me know if there was something i have missed or something i will do to make it work. I have paste my snippets of code down below. It is my pleasure if you give me some time to notice my concern. I have seen similar topic of my issue but it did not help me work out or i have implemented it wrong. Thank you in advance.
I have zxing jar library for generating qr code, and i used me.dm7.barcodescanner:zxing:1.8.4 for scanning qr codes:
dependency {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile files('libs/zxing-2.1.jar')
compile('me.dm7.barcodescanner:zxing:1.8.4'){
exclude group: 'com.google.zxing'
}
}
The Activity for the opening of the camera:
public class ScanQRCodeActivity extends AppCompatActivity implements ZXingScannerView.ResultHandler {
private String strDataEncrypted;
private ZXingScannerView mScannerView;
public static String strEncrypt;
public static String strEncrypted;
public static String strIV;
public static boolean isScanSuccess = false;
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
mScannerView = new ZXingScannerView(this);
setContentView(mScannerView);
}
#Override
public void onResume() {
super.onResume();
mScannerView.setResultHandler(this);
mScannerView.startCamera();
}
#Override
public void onPause() {
super.onPause();
mScannerView.stopCamera();
}
#Override
public void handleResult(Result result) {
strDataEncrypted = result.getText();
Log.wtf("handleResult", strDataEncrypted);
String[] strSplit = strDataEncrypted.split("\\|\\|");
strEncrypted = strSplit[0].trim();
strIV = strSplit[1];
CryptLibHelper cryptLibHelper = new CryptLibHelper();
cryptLibHelper.decrypt(strEncrypted, strIV, new CryptLibHelper.CryptLibDecryptCallback() {
#Override
public void onDecryptFailed(String str_message) {
Log.wtf("onDecryptFailed", str_message);
}
#Override
public void onDecryptSuccess(String str_message) {
if (str_message.contains("}")) {
strEncrypt = str_message.replace("}", "");
Log.wtf("onDecryptSuccess", strEncrypt);
}
}
});
onBackPressed();
isScanSuccess = true;
mScannerView.resumeCameraPreview(this);
}
}
Have you added CAMERA permission check in your app?? Since from marshmallow onwards you need to ask user for some permissions.
You can first try to manually give permission to your app from device settings.
I was experiencing this issue on and off, my problem was that my application was requesting camera permissions too late! Make sure your application is requesting the camera permissions BEFORE an instance of ZXing qr scanner is created.
I am writing a test for a ViewModel. The function in the ViewModel is this:
public void discoverMovies(boolean showLoading) {
// reset the states to initial states
moviesLoading.set(showLoading);
errorViewShowing.set(false);
emptyViewShowing.set(false);
mMoviesRepository.getPopularMovies(1)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribeWith(new DisposableObserver<List<Movie>>() {
#Override
public void onNext(List<Movie> value) {
// show or hide empty view
boolean isEmpty = value == null || value.isEmpty();
if (!isEmpty) {
saveResponse(value);
movies.clear();
movies.addAll(value);
}
emptyViewShowing.set(isEmpty);
}
#Override
public void onError(Throwable throwable) {
errorViewShowing.set(true);
moviesLoading.set(false);
emptyViewShowing.set(false);
errorString.set(getErrorMessage(throwable));
}
#Override
public void onComplete() {
moviesLoading.set(false);
errorViewShowing.set(false);
}
});
}
private void saveResponse(final MovieResponse mainResponse) {
Realm.getDefaultInstance().executeTransaction(new Realm.Transaction() {
#Override public void execute(Realm realm) {
RealmMovie realmMovie = realm.createObject(RealmMovie.class);
realmMovie.setId(1);
realmMovie.setMarvelResponse(new Gson().toJson(mainResponse));
}
});
}
And I test the function above in my test class like this:
Note: Everything works without the Realm aspect. I've confirmed that.
#Test
public void getPopularMoviesWithoutError() {
// given the following movies
when(mMoviesRepository.getPopularMovies(PAGE)).thenReturn(Observable.just(MOVIES));
// discover popular movies
mMoviesViewModel.discoverMovies(true);
// verify that the repository is called
verify(mMoviesRepository).getPopularMovies(PAGE);
// test that the loading indicator is hidden
assertFalse(mMoviesViewModel.moviesLoading.get());
// check that the empty view is hidden
assertFalse(mMoviesViewModel.emptyViewShowing.get());
// check that the error view is hidden
assertFalse(mMoviesViewModel.errorViewShowing.get());
assertTrue(mMoviesViewModel.movies.size() == MOVIES.size());
}
And it keeps on giving me java.lang.IllegalStateException: CallRealm.init(Context)before calling this method. How can I initialize Realm
to be available
I think the error message you are getting is quite clear about what is causing the problem. You are not calling Realm.init.
There are several ways of doing this. The simplest is the #Before and #After annotations on the test suite. You could also use a TestRule
Unfortunately, Realm.init requires a Context. To get that context, you are going to have to be in some environment that has one. That means that you will either have to run your tests on a device, as Instrumentation tests or, as #David Rawson suggests, use Robolectric.
i have a sales summary print out and has a QR Code ,
i want to develop an app (IOS and android) that reads the QR code , extract all information,do some calculations,and display in specific form , i tried zxing library but it did not extract all information from the receipt.any tip?
You can use google vision API to achieve this. I personally used this and found it great. The below code snippets should help you.
Put this below line in the gradle.
compile 'com.google.android.gms:play-services:9.4.0'
Use BarcodeDetector and CameraSource classes to capture the QR code on real time and decode it.
barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> barcodes = detections.getDetectedItems();
if (barcodes.size() != 0) {
barcodeInfo.post(new Runnable() { // Use the post method of the TextView
public void run() {
barcodeInfo.setText( // Update the TextView
barcodes.valueAt(0).displayValue
);
}
});
}
}
});
Use a SparseArray to fetch the detections and the displayValue of the elements of this sparse array returns the deocded string.
After extracting the string one can do anything, be it displaying the string or make some calculation out of it etc.
This library is the most popular and easiest of reading QR codes in your Android application.
You should also have a look at the Wiki section of this library for learning about how to integrate this library into your Android Application and how to use this library.
This is how you can use this library.
1. Add this library to your project by adding following line into your dependencies inside build.gradle(Module: app) file
compile 'com.github.nisrulz:qreader:2.0.0'
2. Then, after syncing project files, add the SurfaceView element provided by this library into your XML layout file.
<SurfaceView
android:id="#+id/camera_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
3. Declare the SurfaceView & QREader inside your Activity's Java file & then initialize it inside onCreate() method.
class MainActivity extends AppCompatActivity{
private SurfaceView mySurfaceView;
private QREader qrEader;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Setup SurfaceView
// -----------------
mySurfaceView = (SurfaceView) findViewById(R.id.camera_view);
// Init QREader
// ------------
qrEader = new QREader.Builder(this, mySurfaceView, new QRDataListener() {
#Override
public void onDetected(final String data) {
Log.d("QREader", "Value : " + data);
text.post(new Runnable() {
#Override
public void run() {
text.setText(data);
}
});
}
}).facing(QREader.BACK_CAM)
.enableAutofocus(true)
.height(mySurfaceView.getHeight())
.width(mySurfaceView.getWidth())
.build();
}
4. Initialize it inside onResume()
#Override
protected void onResume() {
super.onResume();
// Init and Start with SurfaceView
// -------------------------------
qrEader.initAndStart(mySurfaceView);
}
There are many more possibilities you can do with this library, so I recommend you to visit the GitHub repository and check it out. It's worth a shot!
I am trying to implement a referral code system, and I am using Branch.io Metrics library. The problem I am facing is that the documentation is not good (doesn't work) and I am unable to generate a code
Documentation:
https://github.com/BranchMetrics/Branch-Android-SDK#register-an-activity-for-direct-deep-linking-optional-but-recommended
Here are the steps I have taken including adding the library.
1) Grabbed the jar, added to my libs folder and added the following to my depenencies
compile files('libs/branch-1.5.9.jar')
2) In my application class that extends Application I added the following
if (DEBUG) {
Branch.getAutoTestInstance(this);
} else {
Branch.getAutoInstance(this);
}
3) In my AndroidManifest.xml I added the following
<meta-data android:name="io.branch.sdk.BranchKey" android:value="#string/bnc_app_key" />
4) In the Activity that I am testing everything, I added in the onStart() method the following
#Override
protected void onStart() {
// note that branch is a global variable (Branch branch;)
if (DEBUG) {
branch = Branch.getTestInstance(this.getApplicationContext());
} else {
branch = Branch.getInstance(this.getApplicationContext());
}
branch.initSession(new BranchReferralInitListener() {
#Override
public void onInitFinished(JSONObject jsonObject, BranchError branchError) {
if (branchError == null) {}
}, this.getIntent().getData(), this;
}
From the above, I believe I have successfully created a branch.io session and a listener that will allow me to retrieve data if branchError is null (there are no conflicts)
While still inside onStart() I now try to generate a referral code. So the whole onStart() looks as follows:
#Override
protected void onStart() {
// note that branch is a global variable (Branch branch;)
if (DEBUG) {
branch = Branch.getTestInstance(this.getApplicationContext());
} else {
branch = Branch.getInstance(this.getApplicationContext());
}
branch.initSession(new BranchReferralInitListener() {
#Override
public void onInitFinished(JSONObject jsonObject, BranchError branchError) {
if (branchError == null) {}
}, this.getIntent().getData(), this;
}
branch.getReferralCode(5, new BranchReferralInitListener() {
#Override
public void onInitFinished(JSONObject jsonObject, BranchError branchError) {
try {
String code = jsonObject.getString("referral_code");
Log.d(TAG, "code: " + code);
} catch (JSONException e) {
Log.e(TAG, "JSONException :: " + e);
e.printStackTrace();
}
}
});
}
5) I added onNewIntent override method
#Override
protected void onNewIntent(Intent intent) {
this.setIntent(intent);
}
My app does not reach inside of the onInitFinished listener, so I am unable to retrieve any code(s). Any suggestions on what I have missed is appreciated, and hopefully this thread will fill the holes that the documentation lacks.
I'm going to assume that the following lines of code are properly closed and aren't throwing syntax errors:
branch.initSession(new BranchReferralInitListener() {
#Override
public void onInitFinished(JSONObject jsonObject, BranchError branchError) {
if (branchError == null) {}
}, this.getIntent().getData(), this); // parenthesis wasnt here
First, if you are extending the Application class, you need to initialize branch inside the onCreate() callback of your Application class:
public void onCreate() {
super.onCreate();
Branch.getInstance(this);
}
As per the Branch sample code found here, you actually need to call:
Branch.getInstance();
Instead of:
Branch.getInstance(getApplicationContext());
Inside your activities onCreate callback. Once that is taken care of, the Branch SDK will properly create.
I have an API interface and I'm testing a View that involves network calls.
#Config(emulateSdk = 18)
public class SampleViewTest extends RobolectricTestBase {
ServiceApi apiMock;
#Inject
SampleView fixture;
#Override
public void setUp() {
super.setUp(); //injection is performed in super
apiMock = mock(ServiceApi.class);
fixture = new SampleView(activity);
fixture.setApi(apiMock);
}
#Test
public void testSampleViewCallback() {
when(apiMock.requestA()).thenReturn(Observable.from(new ResponseA());
when(apiMock.requestB()).thenReturn(Observable.from(new ResponseB());
AtomicReference<Object> testResult = new AtomicReference<>();
fixture.updateView(new Callback() {
#Override
public void onSuccess(Object result) {
testResult.set(result);
}
#Override
public void onError(Throwable error) {
throw new RuntimeException(error);
}
});
verify(apiMock, times(1)).requestA();
verify(apiMock, times(1)).requestB();
assertNotNull(testResult.get());
}
}
For some reason apiMock methods are never called and verification always fails.
In my view I'm calling my api like this
apiV2.requestA()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer());
What am I missing here?
Update #1:
After some investigation it appears that when in my implementation (sample above) I observeOn(AndroidSchedulers.mainThread()) subscriber is not called. Still do not know why.
Update #2:
When subscribing just like that apiV2.requestA().subscribe(new Observer()); everything works just fine - mock api is called and test passes.
Advancing ShadowLooper.idleMainLooper(5000) did nothing. Even grabbed looper from handler in HandlerThreadScheduler and advanced it. Same result.
Update #3:
Adding actual code where API is used.
public void updateView(final Callback) {
Observable.zip(wrapObservable(api.requestA()), wrapObservable(api.requestB()),
new Func2<ResponseA, ResponseB, Object>() {
#Override
public Object call(ResponseA responseA, ResponseB responseB) {
return mergeBothResponses(responseA, responseB);
}
}
).subscribe(new EndlessObserver<Object>() {
#Override
public void onError(Throwable e) {
Log.e(e);
listener.onError(e);
}
#Override
public void onNext(Object config) {
Log.d("Configuration updated [%s]", config.toString());
listener.onSuccess(config);
}
});
}
protected <T> Observable<T> wrapObservable(Observable<T> observable) {
return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
I'm still wrapping my head around how to properly use rxjava myself but I would try to modify your code so that you only observeOn(mainThread) on the final zipped Observable instead of doing it on both of the original request response's Observable. I would then verify if this affect the fact that you have to advance both Loopers or not.
To simply your tests and remove the need for Looper idling I would take the threading out of the equation since you don't need background processing when running tests. You can do that by having your Schedulers injected instead of creating them statically. When running your production code you'd have the AndroidSchedulers.mainThread and Schedulers.io injected and when running tests code you would inject Schedulers.immediate where applicable.
#Inject
#UIScheduler /* Inject Schedulers.immediate for tests and AndroidSchedulers.mainThread for production code */
private Scheduler mainThreadSched;
#Inject
#IOScheduler /* Inject Scheduler.immediate for tests and Schedulers.io for production code */
private Scheduler ioSched;
public void updateView(final Callback) {
Observable.zip(wrapObservable(api.requestA()), wrapObservable(api.requestB()),
new Func2<ResponseA, ResponseB, Object>() {
#Override
public Object call(ResponseA responseA, ResponseB responseB) {
return mergeBothResponses(responseA, responseB);
}
}
).observeOn(mainThreadSched)
.subscribe(new EndlessObserver<Object>() {
#Override
public void onError(Throwable e) {
Log.e(e);
listener.onError(e);
}
#Override
public void onNext(Object config) {
Log.d("Configuration updated [%s]", config.toString());
listener.onSuccess(config);
}
});
}
protected <T> Observable<T> wrapObservable(Observable<T> observable) {
return observable.subscribeOn(ioSched);
}
what version of rxjava are you using? I know there was some changes in the 0.18.* version regarding the ExecutorScheduler. I had a similar issue as you when using 0.18.3 where I wouldn't get the onComplete message because my subscription would be unsubscribe ahead of time. The only reason I'm mentioning this to you is that a fix in 0.19.0 fixed my issue.
Unfortunately I can't really explain the details of what was fixed, it's beyond my understanding at this point but if it turns out to be the same cause maybe someone with more understand could explain. Here's the link of what I'm talking about https://github.com/Netflix/RxJava/issues/1219.
This isn't much of an answer but more a heads up in case it could help you.
As #champ016 stated there were issues with RxJava versions that are lower than 0.19.0.
When using 0.19.0 the following approach works. Although still don't quite get why I have to advance BOTH loopers.
#Test
public void testSampleViewCallback() {
when(apiMock.requestA()).thenReturn(Observable.from(new ResponseA());
when(apiMock.requestB()).thenReturn(Observable.from(new ResponseB());
AtomicReference<Object> testResult = new AtomicReference<>();
fixture.updateView(new Callback() {
#Override
public void onSuccess(Object result) {
testResult.set(result);
}
#Override
public void onError(Throwable error) {
throw new RuntimeException(error);
}
});
ShadowLooper.idleMainLooper(5000);
Robolectric.shadowOf(
Reflection.field("handler")
.ofType(Handler.class)
.in(AndroidSchedulers.mainThread())
.get().getLooper())
.idle(5000);
verify(apiMock, times(1)).requestA();
verify(apiMock, times(1)).requestB();
assertNotNull(testResult.get());
}