These days I took part in a company-run programming marathon, and I intend to use the Android camera to do it. I've always thought that the Android API was bad, but it didn't say exactly what was bad or how it would be better to improve. Take this opportunity and I'll explain it now.
I think Android's API for webcam is awful, if you haven't used it, take a moment to see it. Using this Camera API often causes developers to use errors, which can lead to developers ignoring a lot of important things, and then it's hard to find out, even in StackOverflow. In other words, if you have an API that requires you to read 10 steps (and a few that are labeled "important"), then it's problematic, how can you write such a troublesome API? We need to improve it.
So I'm going to re-construct it. I put the reconstructed code on GitHub (Easycamera), and here's what I changed, and why I changed it:
Before using the Startpreview () method, you need to call Setpreviewdisplay (..) method, and then you need to call it when you take a picture. Why not improve it? If we do not execute this method, we can simply throw an exception "Preview Display not set", but it is not very good after all. So, this setpreviewdisplay (..) No, we'll just let Startpreview (..). Take surface as a parameter, and then overload it so that Surfacetexture is also passed in as a parameter.
After you have improved the preview settings, you are now starting to improve the preview operation. If you don't call Startpreview this way when you take a picture, you can also throw an exception "Preview not started" here, but know that this exception is thrown at runtime. So, Takepicture (..) This method also needs to be improved, move it outside the camera class, and put it in the Cameraaction class. Other methods that need to be used after the preview call will also need to be improved (I don't know for a moment what is in the current API). The next step is how to get an instance of the Cameraaction class, which is simple and calls Startpreview directly (..) You can return a cameraaction.
At the moment, our improvement is just to make the usage more intuitive and then reduce the error situation. But takepicture this method seems a bit strange, you can give its parameters all null values, but there are still two of the overridden methods require these parameters. Theoretically, null values can be passed, but there are other ways to solve the problem. One is to introduce an interface called Picturecallback, which has four methods that can be called, and then provides a default implementation class called Basepicturecallback. Of course, you will find that it seems inappropriate in this scenario, because in this case you pass the callback interface and nothing happens, but if you pass a null value, it will be different (there will be a problem), but when I test on my phone, I pass a shutter callback, the shutter sound will ring and the null value will not be transmitted. So, the main thing here is to use this callback interface with an implementation class that contains all the methods you need.
So far, the change is good, there is, after the photo is completed, need restart preview, but the default let it automatically restart is not very good. The current situation is that we have only one Cameraaction class and then call Startpreview (..) Method needs to pass a surface parameter, is it necessary to introduce a restartpreview () method? Of course not, we let the method of this interface class return a Boolean value, if need restart Preview, can return true, this will be better, then there is a problem, if the callback class does not have these 4 method calls, rely on these 4 methods to determine whether the need Restart preview is not good after all, so you also need to add a Restartpreview attribute in the callback implementation class, which is set to true only when the last method is invoked.
The main steps have been improved, and there are other minor problems to be improved, such as the way to close and open the camera is asymmetric, "open" and "release" pairing feel bad, should be "open" and "close" or "acquire" and "release ”。 So I think the "close" is better, and (if you use Java7), you can take advantage of the Autoclosable interface, as well as the Try-with-resource structure (see Java7 new features for details).
You can get a copy of the parameter when you call the GetParameter () method, and then you may need to set the changed copy back, which is quite reasonable. If you can provide a camera.setparameter (..) method, may be easier to use, but the parameter class has provided a lot of methods, so it is not very good to add in the camera class. Perhaps variable parameters can be set here? (Of course it's not yet)
One of the reasons why this camera's API is bad is that it has error feedback, which basically may get an error message "Came.takepicture failed", whatever the cause, through these steps, in some cases will filter out some of the exception information we need, However, it is best to get accurate error messages.
Our goal is to make the camera more user friendly (not yet), so Easycamera is an easy-to-use interface, and Cameraactions is a very good class to build.
My Easycamera project is only a first edition, but also not used in the actual production environment, but I also hope to get everyone's valuable advice, strive to do it better, and constantly improve it. In some cases, it can also include other features of the camera, such as front and rear camera switching and so on.
Crappy APIs can make developers waste a lot of time, money and energy, so when designing an API, you need some special skills and more thinking. Josh Bloch's insight into API design is very pertinent, and I highly recommend it. In fact, I also violated one of them-"If in doubt, leave it out"-by cameraaction this class we can take full control of the camera, so there may be a lot of operation is useless, because I do not know the properties of all camera, So in the code I will not restrict the user to do some other operation.
When I first wrote this article, I didn't actually intend to write easycamera, but I actually spent two hours writing it out. Finally, I recommend that all developers, when you encounter some crappy API, you can do the same as above, do some self-improvement, think about how to design and implement them, and then you will find it easier than you slowly modify and seal, and then use it handy.