为什么需要在onPause()而不是onstop()方法中释放Camera?

时间:2012-08-07 03:51:30

标签: android api camera mediarecorder

我似乎错过了一些东西,因为我无法理解为什么在Android文档(Android Camera doc. link)中建议在onPause()Activity回调中释放Camera对象(以及MediaRecorder)?到那时候Activity仍然可以看到,Camera可能正在运行预览,那么为什么Camera对象会在onPause()而不是onStop()中被释放?我知道MediaRecorder对象可以在onPause()中停止,但Camera本身对我没有意义。我在这里错过了什么? Android文档中的一段代码如下(在Releasing the Camera标题下):

    @Override
protected void onPause() {
    super.onPause();
    releaseMediaRecorder();       // if you are using MediaRecorder, release it first
    releaseCamera();              // release the camera immediately on pause event
}

private void releaseMediaRecorder(){
    if (mMediaRecorder != null) {
        mMediaRecorder.reset();   // clear recorder configuration
        mMediaRecorder.release(); // release the recorder object
        mMediaRecorder = null;
        mCamera.lock();           // lock camera for later use
    }
}

4 个答案:

答案 0 :(得分:3)

一旦您的活动收到onPause消息,就意味着用户可能正在使用或将要使用其他应用程序..在这种情况下,如果他尝试通过其他应用程序使用相机,则相机必须被您的应用程序释放或释放

答案 1 :(得分:2)

根据application lifecycle

Paused
    Another activity is in the foreground and has focus, but this one is 
            still visible. That is, another activity is visible on top of this 
            one and that activity is partially transparent or doesn't cover the 
            entire screen. (...)

我认为文档遵循拇指规则“尽快释放资源”:onPause早于onStop

背景窗口中的摄像头需要能量,而用户必须注意弹出窗口。

背景中的相机当然更舒适,但对于移动电池来说,续航时间更为重要。

拦截你活动的弹出窗口可能需要摄像头和/或可能需要大量内存。

在摄像机应在后台继续录制的情况下,摄像机的生命周期和录制应由服务控制

答案 2 :(得分:0)

  

由于无法保证调用#include <boost/graph/adjacency_list.hpp> #include <boost/graph/vf2_sub_graph_iso.hpp> #include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/classification.hpp> #include <boost/config.hpp> #include <boost/graph/isomorphism.hpp> #include <boost/graph/graph_utility.hpp> #include <boost/tuple/tuple_comparison.hpp> #include <fstream> #include <iostream> #include <vector> //for mmap: #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> using namespace boost; //==========STRUCTURES========== // vertex struct VertexProperties { int id; int label; VertexProperties(unsigned i = 0, unsigned l = 0) : id(i), label(l) {} bool operator==(VertexProperties const& other) const { return tie(id, label) == tie(other.id, other.label); } }; // edge struct EdgeProperties { unsigned label; EdgeProperties(unsigned l = 0) :label(l) {} bool operator==(EdgeProperties const& other) const { return tie(label) == tie(other.label); } }; // Graph struct GraphProperties { unsigned id; unsigned label; GraphProperties(unsigned i = 0, unsigned l = 0) : id(i), label(l) {} }; // adjency list typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, VertexProperties, EdgeProperties, GraphProperties> Graph; // descriptors typedef boost::graph_traits<Graph>::vertex_descriptor vertex_t; typedef std::pair<boost::graph_traits<Graph>::edge_descriptor, bool> edge_t; // iterators typedef graph_traits<Graph>::vertex_iterator vertex_iter; typedef graph_traits<Graph>::edge_iterator edge_iter; typedef std::pair<edge_iter, edge_iter> edge_pair; //*********global variables************* std::vector<Graph> dataG; //=================callback used fro subgraph_iso================================================================= // Default print_callback template <typename Graph1,typename Graph2> struct my_callback { my_callback(const Graph1& graph1, const Graph2& graph2) : graph1_(graph1), graph2_(graph2) {} template <typename CorrespondenceMap1To2, typename CorrespondenceMap2To1> bool operator()(CorrespondenceMap1To2 /*f*/, CorrespondenceMap2To1) const { return true; } private: const Graph1& graph1_; const Graph2& graph2_; }; //==========handle_error========== void handle_error(const char *msg) { perror(msg); exit(255); } //============READ ALL THE FILE AND RETURN A STRING=================== const char *readfromfile(const char *fname, size_t &length) { int fd = open(fname, O_RDONLY); if (fd == -1) handle_error("open"); // obtain file size struct stat sb; if (fstat(fd, &sb) == -1) handle_error("fstat"); length = sb.st_size; const char *addr = static_cast<const char *>(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0u)); if (addr == MAP_FAILED) handle_error("mmap"); // TODO close fd at some point in time, call munmap(...) return addr; } //==========SPLIT THE STRING BY NEWLINE (\n) ========== std::vector<std::string> splitstringtolines(std::string const& str) { std::vector<std::string> split_vector; split(split_vector, str, is_any_of("\n")); return split_vector; } //============Get a string starting from pos============ std::string getpos(int const& pos, std::string const& yy) { size_t i = pos; std::string str; for (; ((yy[i] != ' ') && (i < yy.length())); i++) {str += yy[i];} return str; } //==================read string vector and return graphs vector=================== std::vector<Graph> creategraphs(std::vector<std::string> const& fichlines) { for (std::string yy : fichlines) { switch (yy[0]) { case 't': { std::string str2 = getpos(4, yy); unsigned gid = atoi(str2.c_str()); dataG.emplace_back(GraphProperties(gid, gid)); } break; case 'v': { assert(!dataG.empty()); // assert will terminate the program if its argument turns out to be false // std::cout<<yy<<std::endl; int vId, vLabel; std::string vvv = getpos(2, yy); vId = atoi(vvv.c_str()); std::string vvvv = getpos((int)vvv.length() + 3, yy); // std::cout<<vvvv<<std::endl; vLabel = atoi(vvvv.c_str()); boost::add_vertex(VertexProperties(vId, vLabel), dataG.back()); } break; case 'e': { // std::cout<<yy<<std::endl; assert(!dataG.empty()); // assert will terminate the program if its argument turns out to be false int fromId, toId, eLabel; std::string eee = getpos(2, yy); // std::cout<<eee<<std::endl; fromId = atoi(eee.c_str()); std::string eee2 = getpos((int)eee.length() + 3, yy); // std::cout<<eee2<<std::endl; toId = atoi(eee2.c_str()); int c = (int)eee.length() + (int)eee2.length() + 4; // std::cout<<c<<std::endl; std::string eee3 = getpos(c, yy); // std::cout<<eee3<<std::endl; eLabel = atoi(eee3.c_str()); for (size_t i = 0; i < num_vertices(dataG.back()); ++i) // size_t vertice number in the graph { if(dataG.back()[i].id==fromId) fromId=i; else if(dataG.back()[i].id==toId) toId=i; } boost::add_edge(fromId, toId, EdgeProperties(eLabel), dataG.back()); } break; } } return dataG; } template <typename Graph1, typename Graph2> bool my_bundled_graph_iso(Graph1 const& graph_small, Graph2 const& graph_large) { auto const vos = boost::copy_range<std::vector<Graph::vertex_descriptor> >(vertices(graph_small)); return vf2_subgraph_iso(graph_small, graph_large, my_callback<Graph, Graph>(graph_small, graph_large), vos, edges_equivalent (make_property_map_equivalent(boost::get(edge_bundle, graph_small), boost::get(edge_bundle, graph_large))). vertices_equivalent(make_property_map_equivalent(boost::get(vertex_bundle, graph_small), boost::get(vertex_bundle, graph_large))) ); } //==============================M A I N P R O G R A M ======================================= int main() { size_t length; std::vector<Graph> dataG = creategraphs(splitstringtolines(readfromfile("2.txt", length))); std::cout << std::boolalpha << my_bundled_graph_iso(dataG[0], dataG[1]) << std::endl; } (),因此您无法始终在onStop()中执行onStop

中的操作

<强> For Detail Answer

始终会调用

onPause().。这是有保证的。如果您需要在活动中保存任何状态,则需要将其保存在onPause()中,可以在onPause()之后调用,也可以不调用。取决于具体情况。

答案 3 :(得分:-1)

onPause意味着您的活动不再可见。

只有在Android不再认为您的流程需要时才会调用onStop。