'monitor' require 'camera_helper' require 'ruboto/util/stack' class SpycamServer extend MonitorMixin PORT = 4567 DOC_ROOT = "#{$activity.files_dir.absolute_path}/" @@server = nil def self.start(activity, server_status_view) Thread.with_large_stack(512) do synchronize do if @@server.nil? activity.run_on_ui_thread { server_status_view.text = "Loading" } require 'webrick' activity.run_on_ui_thread { server_status_view.text = "Loaded" } @@server = WEBrick::HTTPServer.new(:Port => PORT, :DocumentRoot => DOC_ROOT) @@server.mount_proc('/') do |req, resp| case req.path when '/', 'index.html' CameraHelper.take_picture(activity) resp.content_type = "text/html" resp.body = '<html> <head> <title>Spycam</title> </head> <body> <a href="/"><img src="latest.jpg"></a> </body> </html>' raise WEBrick::HTTPStatus::OK when '/latest.jpg' resp.content_type = "image/jpg" resp.body = $camera_data $camera_data = nil raise WEBrick::HTTPStatus::OK else resp.body = "Unknown path: #{req.path.inspect}" raise WEBrick::HTTPStatus::NotFound end end server = @@server Thread.new{server.start} require 'ruboto/activity' require 'ruboto/widget' require 'spycam_server' import android.util.Log import android.view.Surface import android.view.WindowManager ruboto_import_widgets :Button, :LinearLayout, :ScrollView, :TextView ruboto_import_widget :SurfaceView, "android.view" class SpycamActivity def on_create(bundle) rotation = { Surface::ROTATION_0 => 0,Surface::ROTATION_90 => 90,Surface::ROTATION_180 => 180,Surface::ROTATION_270 => 270 }[window_manager.default_display.rotation] self.title = "Spycam #{rotation}" # self.setRequestedOrientation(android.content.pm.ActivityInfo::SCREEN_OR IENTATION_PORTRAIT) window.add_flags(WindowManager::LayoutParams::FLAG_KEEP_SCREEN_ON) setContentView(linear_layout(:orientation => :vertical) do linear_layout do text_view :text => "Server: " @server_status_view = text_view end linear_layout do text_view :text => "Picture: " @camera_status_view = text_view end sv = surface_view sv.holder.add_callback RubotoSurfaceHolderCallback.new(rotation) # Deprecated, but still required for older API version sv.holder.set_type android.view.SurfaceHolder::SURFACE_TYPE_PUSH_BUFFERS end) end def set_camera_status(value) @camera_status_view.text = value end def camera_status=(value) run_on_ui_thread { $activity.set_camera_status value } end def on_resume class CameraHelper def self.take_picture(activity) activity.camera_status = "Set volume..." am = activity.getSystemService(android.content.Context::AUDIO_SERVICE) old_volume = am.get_stream_volume(android.media.AudioManager::STREAM_SYSTEM) am.set_stream_volume(android.media.AudioManager::STREAM_SYSTEM, 0, 0) activity.camera_status = "Taking picture..." picture_taken = false $camera.take_picture(nil, nil) do |data, camera| $camera_data = String.from_java_bytes(data) activity.camera_status = "Gotcha!" $camera.start_preview am.set_stream_volume(android.media.AudioManager::STREAM_SYSTEM, old_volume, 0) picture_taken = true end sleep 0.1 until picture_taken end end