I am trying to use ZMQ in an android application. Ideally, I should create the context once and term() it when the app is shutting down.
But unlike the c++ applications. There is no main() function on android. Based on the google document about the activity life cycle. The function onCreate(), onStop() can be called multiple times, the function onDestroy() is only called by system.
Solution1: create/destroy ZMQ context in an asyncTask(). But that would be very expensive.
Solution2: based on the thread Android global variable, I could create a global ZMQ.Context contextvariable. The problem of this method is: there is not proper function to call context.term();.
solution3. Creating a singleton class
import org.zeromq.ZMQ;
public class ZmqHelper {
private static ZMQ.Context _context;
public static ZMQ.Context createContext(){
return getContext();
}
public static ZMQ.Context getContext(){
if(_context == null) {
_context = ZMQ.context(1);
}
return _context;
}
private ZmqHelper(){
}
public static boolean release(){
// make sure all sockets are closed
if(_context != null) {
_context.term();
_context = null;
return true;
}
return false;
}
}
The problem of the singleton is same as solution 2. I have to manually call ZmqHelper.release() //which calls context.term() in some stage. I am not sure where is the good place to invoke the function term() to destroy zmq context.
So what is the correct way to create/terminate a ZMQ context in an android application?
env:
Ubuntu: 16.04 LTS
Android studio: 2.3.3
ZMQ: org.zeromq:jeromq:0.4.0
I think you shall use a singletone instance as more straightforward solution.
All network communication on Android must be held is a separate thread (not UI-thread). So you may term ZMQ.Context when you interrupt the networking thread. If your app doesn't need background network connection (you perform netwroking only at separate Activities) it's better to term ZMQ.Context in onPause() methods of those Activities for performance reasons.
I am using such approach but meet problems with terminating SUB socket. Though I think the approach is pretty well.
Related
I'm making image processor app. I need to scan the phone for pictures and list them with their number of pixels. So that's gonna be a a large impact on performance and as I understood, I need to make it work on background thread.
So my question is, what is the best approach for this? I understand that IntentService may be the best solution, but I'm not sure how I will implement progress bar with it, and I need to return Picture objects and later update the UI on shuffle button. I'm doing update with Glide library so that's gonna go smooth.
Reading about Asynctasks, I stumbled about comments how it's bad and leads to leaks in memory and should avoid using it. rXJava is too complicated at the moment.
This is my code:
Main activity:
#OnClick(R.id.shuffle)
public void shuffleList() {
Collections.shuffle(listOfImageFiles);
recyclerViewAdapter = new PictureRecycleViewAdapter(listOfImageFiles, this);
recyclerView.swapAdapter(recyclerViewAdapter, false);
recyclerViewAdapter.notifyDataSetChanged();
}
#OnClick(R.id.scan)
public void processImages() {
//progress bar
listOfPictures = new ArrayList<>();
//Gets data from default camera roll directory. Note that some of the phone companies have different file paths. So instead of hardcoding string paths, I used this instead.
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath();
File filePath = new File(path);
listOfImageFiles = scanPhotos(filePath);
// async?
for (File file : listOfImageFiles
) {
Bitmap bitmap = BitmapFactory.decodeFile(file.getPath());
//int is sufficient for most today's pixels. long would be overkill - 4 vs 8 bytes
int pixels = bitmap.getHeight() * bitmap.getWidth();
listOfPictures.add(new Picture(file.getPath(), pixels));
}
}
public List<File> scanPhotos(File directory) {
List<File> listOfPictures = new ArrayList<>();
try {
File[] files = directory.listFiles();
for (File file : files
) {
if (file.isDirectory() && !file.isHidden()) {
listOfPictures.addAll(scanPhotos(file));
} else {
if (file.getName().endsWith(".jpg") || file.getName().endsWith(".jpeg") || file.getName().endsWith(".png")) {
listOfPictures.add(file);
}
}
}
} catch (Exception e) {
Log.e(e.getMessage(), e.getMessage());
}
return listOfPictures;
}
IntentService
IntentService is definitely a valid approach. You can use Broadcasts to return your result to another component of the app, be it Activity or another Service, for example:
Start the IntentService - if you need some parameters, place them in the Extras of the service intent.
Your IntentService runs on the background thread until the computation is finished.
Upon finishing, send a broadcast with computation result placed in intent extras.
In your activity, register a BroadcastReceiver that will listen for your computation result broadcast.
Upon getting the broadcast in your Activity, retrieve the computation result from intent extras.
You might also implement broadcasts received by your Service for things like cancellation of the computation or updating the parameters.
One of the advantages of IntentService is that you can easily integrate it with the JobScheduler API to defer execution until certain system conditions are met.
Alternatives
You can use a bus library, such as https://github.com/greenrobot/EventBus to communicate between Activity and Service - the only problem is, EventBus won't work with remote services (running in a separate process).
Like you've mentioned, using RxJava with IO and computation schedulers is also a good idea.
AsyncTask is fine as long as you not tie it with a hard reference to an activity - don't implement it as an inner class of Activity and if you want to communicate the result back, do it through a WeakReference<T>
AsyncTask is fine, you just need to be careful with its implementation.
However, for longer running tasks there are better options. IntentService is a good option.
When it comes to a responsive UI when using an IntentService you could add two things.
Notifications
Create an ongoing notification that indicates that your App is working on something. This lets users know that their CPU cycles are being eaten by something in the background and they are less likely(?) to be confused and cranky about their device running slower.
Additionally, it gives your App more of an allowance for staying alive when Android is looking for background Apps to kill to release memory.
EventBus
You can make UI reporting extremely simple by using an EventBus library. I am personally a fan of greenbot/EventBus, but there are others.
Example
In your Activity:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onProgressEvent(ProgressEvent event) {
mProgressBar.setProgress(event.value);
}
In your IntentService:
EventBus.getDefault().post(new ProgressEvent(5000));
A work collegue has implemented a class to load native C++ shared libraries into our Android app, he named this class 'LibLoader'. His proposed solution was to instantiate a LibLoader object every time we needed to use one of the native functions declared in the native library. I believe this is not optimum from a performance point of view so I was thinking about the best way to optimize this.
So far two solutions have come into my mind:
Make the LibLoader class a singleton
Turn the native methods into static ones so I won't even have to make an object
Considering native shared libraries are loaded through static/instace initializacion in the class, my questions are:
Which of these two approaches would be the best from a performance point of view? I need my code to be fast, I'm calling these native functions several times to compute FFTs on real time audio samples
Is there another optimum way to do this?
What happens to static/instance initialization if the native methods are converted to static ones? Will it be called every time a static method is accessed?
My code is:
public class LibLoader {
static final String TAG = "LibLoader";
static boolean armv7 ;
static
{
String arch = System.getProperty("os.arch");
//determine which library to load according to CPU type
if(arch.contentEquals("armv7l"))
{
//fftw neon compiled library functions work with armv71 and armv6
try {
System.loadLibrary("fftwfNeon_fftTwiddle"); //this won't load from any other platform
armv7 = true;
}catch (UnsatisfiedLinkError e)
{
Log.e(TAG, "Unable to load fftwfNeon_fftTwiddle library "+ e.getMessage());
}
}
else
{
try {
System.loadLibrary("fftTwiddle");
armv7 = false;
}catch (UnsatisfiedLinkError e)
{
Log.e(TAG, "Unable to load fftTwiddle library "+ e.getMessage());
}
}
}
public native void GetComplexFFtDoubleIN(double[] realIN, double[] imagIN, int fftSize, double[] TW, boolean ifftFlag);
public native void FFTWfNeonSymb(int fftSize, float[] realPart, float[] imagPart, boolean isFFT);
public native void FFTWfNeonSync(int fftSize, float[] realPart, float[] imagPart, boolean isFFT);
}
Having your methods static vs creating an instance variable for the class, does not affect CPU performance much. But these 2 implementations differs a lot in memory usage.
If it is only FFT calculations then, I would suggest to keep it static. This can keep you code free from memory leaks.
Update: Creating a singleton is between the 2 options I have explained. Here are the 3 ways you can do it in the order of memory simplicity.
All methods are static and you directly access the methods from any class you want. (Only has the class in memory)
Having a singleton variable. Creating a new variable will always return the same static variable. (Keeps the class and the static variable in memory)
Creating a new variable and deleting the memory after using the required methods in the class. (Allocates memory when needed and clears it when not in use.)
I'm trying to carry out junit test for the Android-DDP library.
To initialize the meteor object, we need a reference to a android context which I'm able to achieve using Robolectric. But the web-sockets is probably talking to the server on a different thread because of which the callback methods are not called and the test methods are getting end.
I used netstat to check if the android client is trying to communicate or not. It shows various ping/pong messages. So, Yes it is trying to talk to the server.
I went through this tutorial as well,
Android AsyncTask testing with Android Test Framework. This one tells how to handle the network on UI thread. But nothing seems right.
The sample code, I have worked is:
#Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
#RunWith(RobolectricGradleTestRunner.class)
public class MainActivityTest {
private MainActivity activity;
private Meteor meteor;
private String globalUrl = "ws://10.0.3.222:3000/websocket";
#Before
public void setup() {
activity = Robolectric.setupActivity(MainActivity.class);
meteor = new Meteor(activity, globalUrl);
meteor.reconnect();
/*
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
*/
}
#Test
public void validateMeteorIsConnected() {
assertTrue(meteor.isConnected());
}
}
Any help would be appreciable. Thanks in advance.
You defined two methods, setup() and validateMeteorIsConnected(), but where are they called?
First, your setup is not correct. After your call to new Meteor(...), you don't need the reconnect() call because the constructor does already establish the connection.
Moreover, you must set up a listener so that you know when the connection has been established or data comes in. This is done with mMeteor.setCallback(...); where the parameter is this or activity.
As you said, the work is done on a different thread and everything is asynchronous.
So you can't just call validateMeteorIsConnected() immediately after connecting.
You need some timer, as shown in the question that you linked to.
I'm implementing GCM into my Android app. So far so good, the messaging works, but when a message is received, the app may or may not crash with NullPointerException. The reason this happens is because a static reference is sometimes null and sometimes not, but the reason why this happens is unknown to me.
The object that may or may not be null is a MessageController located via a simple service locator pattern, which looks like this:
public class ControllerLocator
{
private static MessageController controller;
public static MessageController getMessageController()
{
return controller;
}
public static void provide(MessageController mc)
{
controller = mc;
}
}
The controller is set up in the application's onCreate() method:
#Override
public void onCreate()
{
super.onCreate();
ControllerLocator.provide(new MessageController());
}
// Later on in the program after backend authentication:
ControllerLocator.getMessageController().setCredentials(...);
The GCM message handling is like this:
#Override
protected void onHandleIntent(Intent intent)
{
Bundle extras = intent.getExtras();
String msgType = GoogleCloudMessaging.getInstance(this).getMessageType(intent);
if(msgType.equals(GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE))
{
handleMessage(extras.getString("message"));
}
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
private void handleMessage(String msg)
{
// 'controller' may or may not be null
MessageController controller = ControllerLocator.getMessageController();
}
Now, the actual scenario: Everything works fine when the app is running in the foreground. However, if I press "back" to exit close the main activity and a GCM message is received, the crash may or may not occur.
Why does the static reference get removed? How would I fix this to ensure that the controller is always there?
Its because your app process is killed and all the memory it held was released while you were waiting for that GCM message.
When your GCM message was incoming the system creates your app process and Application object over again hence you got null.
Simply check if the instance is null on your get instance method and if its null recreate your object.
EDIT:
There is no way to make sure the same object is alive always, Android system is running many apps at once and cant allow any app to fill up memory, therefore it may kill your process whenever other apps need memory and that would automatically release your reserved memory including static varaiables. Its your job as an Android developer to deal with it :)
To avoid reauth and heavy computations on recreation, you may have to rethink your design such that the state of your object is persistent, using SharedPreferences maybe.
You cannot ensure that your static Controller Object will be alive (not null),, Because an app in the background is an ideal candidate for GC.
You could however save your GCM Message data in SQLite at the point where it is received. And then check the table for data, when you open your app.
Make your MessageController variable static.
Has anybody had success integrating the Licensing Verification Library (LVL) with a Live Wallpaper? If it were just running an Activity, it'd be crystal clear to just extend my Activity from the Licensing Activity, which in turn extends Activity. But Live Wallpapers are a Service, and I'm not sure how the two are intended to interact.
I'm using code derived from this: http://www.droidforums.net/forum/android-app-developers/69899-market-license-easy-implementation-protect-your-apps.html which seems to be the code that nearly everything I can find on the web refers to.
I notice that wallpaper settings are an activity, and I have those working properly, but for some reason I can't grok the Licensing stuff...
It's actually really quite simple, you don't need to use any Activity class to implement licensing into a WallpaperService.
Make sure you've followed the directions carefully at http://developer.android.com/guide/publishing/licensing.html
Here's how I did it:
Your extended Engine class should include something similar to the following... (code not essential to your question has been removed)
class startYourEngines extends Engine {
public startYourEngines() {
super();
licenseStatus(); //custom license check method (for modularity)
//the rest of your engine would go here
}
public void onDestroy() {
super.onDestroy();
licenseChecker.onDestroy(); //we call this to close IPC connections
}
//prep work
private static final String BASE64_PUBLIC_KEY = //OMITTED//;
private LicenseCheckerCallback licenseCallback;
private LicenseChecker licenseChecker;
private byte[] salt = "rAnd0mStr!ng".getBytes();
private AESObfuscator aes;
private String deviceId;
//our custom license check method
private void licenseStatus() {
deviceId = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
aes = new AESObfuscator(salt, getPackageName(), deviceId);
licenseCallback = new licenseVerification();
licenseChecker = new LicenseChecker(context, new ServerManagedPolicy(context, aes), BASE64_PUBLIC_KEY);
licenseChecker.checkAccess(licenseCallback);
}
//our callback method
private class licenseVerification implements LicenseCheckerCallback {
#Override
public void allow() {
//allow full app use
}
#Override
public void dontAllow() {
//prevent or limit app use
}
#Override
public void applicationError(ApplicationErrorCode errorCode) {
//error handling here
}
}
}
Licensing on the Android platform was created with versatility in mind. Just be sure to read through the documentation, and you shouldn't have any issues.
I have only written applications that start activities, but looking at my source code, it seems that the only reason that you would have to have an Activity do the license check is to show dialogs.
In all of the examples available on line, the LicenseCheckerCallback implementation always shows a dialog in the allow() and dontAllow() methods. Why not just show a toast in dontAllow() and exit your wallpaper service (call stopSelf(YourService.this))?
Let me know if you want more information, because I dont think you are limited to only using an activity for license checking. As an aside, make sure that you dont keep whole strings, etc in your app or in the preferences. Anyone with root access can access your preferences and if your app is decompiled, your strings are visible...
I think I've actually got it working now. I'm extending LicenseCheckActivity to my own Activity class that I'm calling in the manifest file with the usual MAIN action and LAUNCH category. I instantiate my class, do the license check, and then either allow the wallpaper to function or not based on that result (though the best way to do that is still something I need to sort out).
It almost seems too easy that I think I must be missing something. I'd appreciate anybody with experience with selling a licensed live wallpaper on the Android Market to share whatever wisdom they care to.