SlideShare ist ein Scribd-Unternehmen logo
1 von 110
INTERMEDIATE
ANDROID
Michael Galpin
                 Bump Technologies
ABOUT: ME
 ‣       Android engineer, Bump Technologies

 ‣       ex-eBay: eBay Mobile for Android

 ‣       Android in Practice

 ‣       Social info

     ‣    @michaelg
     ‣    +Michael Galpin
Bump
Technologies
     • Creators of Bump app
       • Android + iOS
       • 65M+ Downloads
     • Creators of BumpCube
     • Hiring!
You down with AIP?
• Chapter 11: “Appeal to
  the senses using
  multimedia.”

• Slideshow app
  MediaMogul.apk

• http://
  code.google.com/p/
  android-in-practice/
MULTIMEDIA
“Of all of our inventions for mass
communication, pictures still speak the
most universally understood language.”

                          -- Walt Disney
DETECTING
CAPABILITIES
AndroidManifest.xml
<uses-feature android:name="android.hardware.camera"
    android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus"
    android:required="true"/>
<uses-feature android:name="android.hardware.camera.flash"
    android:required="false" />
<uses-feature android:name="android.hardware.camera.front"
    android:required="false" />
<uses-feature android:name="android.hardware.microphone"
    android:required="true"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Check the front
private boolean hasFrontFacingCamera(){
    PackageManager mgr = this.getPackageManager();
    for (FeatureInfo fi : mgr.getSystemAvailableFeatures()){
        if (fi.name.equals(PackageManager.FEATURE_CAMERA_FRONT)){
            return true;
        }
    }
    return false;
}

private Camera getFrontFacingCamera(){
    for (int i=0;i<Camera.getNumberOfCameras();i++){
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(i, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){
            return Camera.open(i);
        }
    }
    return null;
}
Check the front
private boolean hasFrontFacingCamera(){
    PackageManager mgr = this.getPackageManager();
    for (FeatureInfo fi : mgr.getSystemAvailableFeatures()){
        if (fi.name.equals(PackageManager.FEATURE_CAMERA_FRONT)){
            return true;
        }
    }
    return false;
}

private Camera getFrontFacingCamera(){
    for (int i=0;i<Camera.getNumberOfCameras();i++){
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(i, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){
            return Camera.open(i);
        }
    }
    return null;
}
But I have to
  support
Android 2.1
Reflection?
LOLZ

// Can't use Build.VERSION_CODES.GINGERBREAD
if (Build.VERSION.SDK_INT >= 9){
    PostFroyoClass wontThisBlowUp = new PostFroyoClass();
}
These are my customers!
These are my customers!
Proprietary APIs FTW!

import com.sprint.hardware.twinCamDevice.FrontFacingCamera;

Camera evoCam = FrontFacingCamera.getFrontFacingCamera();
RESOURCES
MediaPlayer.framework?
MediaPlayer.framework?

[MPMusicPlayerController iPodMusicPlayer] ??
MediaPlayer.framework?

[MPMusicPlayerController iPodMusicPlayer] ??

   [MusicLibrary sharedMusicLibrary] ???
MediaPlayer.framework?

[MPMusicPlayerController iPodMusicPlayer] ??

   [MusicLibrary sharedMusicLibrary] ???
        UIImagePickerController ?
MediaPlayer.framework?

[MPMusicPlayerController iPodMusicPlayer] ??

   [MusicLibrary sharedMusicLibrary] ???
        UIImagePickerController ?
MediaPlayer.framework?

[MPMusicPlayerController iPodMusicPlayer] ??

   [MusicLibrary sharedMusicLibrary] ???
        UIImagePickerController ?




            Files !!!!
Inside your APK




                  External
Just give it to me /res/raw

Resources res = this.getResources();


InputStream stream = res.openRawResource(R.raw.sunflower);


MediaPlayer.create(this, R.raw.constancy).start();
I like big /
     assets
and I cannot lie
MediaPlayer player = new MediaPlayer();
AssetManager mgr = getResources().getAssets();
String audioDir = "audio";
final LinkedList<FileDescriptor> queue =
    new LinkedList<FileDescriptor>();
for (String song : mgr.list("audio")){
    queue.add(
            mgr.openFd(audioDir + "/" + song).getFileDescriptor());
}
if (!queue.isEmpty()){
    FileDescriptor song = queue.poll();
    player.setDataSource(song);
    player.prepare();
    player.start();
}
player.setOnCompletionListener(new OnCompletionListener(){
    @Override
    public void onCompletion(MediaPlayer mp) {
        if (!queue.isEmpty()){
            FileDescriptor song = queue.poll();
            player.setDataSource(song);
            player.prepare();
            player.start();
        }
    }
});
File picturesDir =
    Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES);
File picturesDir =
    Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES);
IMAGES
Loading local images
InputStream stream = new FileInputStream(imgFile);
Bitmap bm = BitmapFactory.decodeStream(stream);
Loading local images
InputStream stream = new FileInputStream(imgFile);
Bitmap bm = BitmapFactory.decodeStream(stream);



// calculate desired width and height



Bitmap thumb = ThumbnailUtils.extractThumbnail(bm, width, height);

Bitmap thumb = Bitmap.createScaledBitmap(bm, width, height, false);
Loading without
                         exploding
public static Bitmap decodeDownsizedBitmapStream(File file, int target, Context context) throws
IOException {
    FileInputStream stream = new FileInputStream(file);
    Pair<Integer, Integer> source = getDimensionsForStream(stream);
    stream.close();
    FileInputStream in = new FileInputStream(file);
    Options options = new Options();
    options.inSampleSize = 1 + getDownSampleSize(max(source.first, source.second), target);
    return BitmapFactory.decodeStream(in, null, options);
}
public static Pair<Integer, Integer> getDimensionsForStream(InputStream in){
    Options options = new Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(in, null, options);
    return new Pair<Integer, Integer>(options.outWidth, options.outHeight);
}
public static int getDownSampleSize(int source, int target){
    int size = 1;
    if (source <= 2*target){
        int power = (int) ((log (source / target)) / log(2));
        size = (int) pow(2, power);
    }
    return size;
}
Loading web images
URL url = new URL(urlString);



//   NOTE, be careful about just doing "url.openStream()"
//   it's a shortcut for openConnection().getInputStream() and doesn't set timeouts
//   the defaults are "infinite" so it will wait forever if endpoint server is down
//   do it properly with a few more lines of code . . .



URLConnection conn = url.openConnection();
conn.setConnectTimeout(3000);
conn.setReadTimeout(5000);

Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream());
AsyncTask FTW!
private class RetrieveImageTask extends AsyncTask<String, Void, Bitmap> {
   private ImageView imageView;

    public RetrieveImageTask(ImageView imageView) {
       this.imageView = imageView;
    }

    @Override
    protected Bitmap doInBackground(String... args) {
       try {
          URL url = new URL(args[0]);
          URLConnection conn = url.openConnection();
          conn.setConnectTimeout(3000);
          conn.setReadTimeout(5000);
          return BitmapFactory.decodeStream(conn.getInputStream());
       } catch (Exception e) {
       }
       return null;
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
       if (bitmap != null) {
          imageView.setImageBitmap(bitmap);
       }
    }
}
Loading a dozen images
       isn’t cool.
 Y’know what’s cool?
Loading a billion images.
Hot or Not?
private class DealsAdapter extends ArrayAdapter<Item> {

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
       if (convertView == null) {
          LayoutInflater inflater = (LayoutInflater)
              getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          convertView = inflater.inflate(R.layout.list_item, parent, false);
       }
       TextView text = (TextView) convertView.findViewById(R.id.deal_title);
       ImageView image = (ImageView) convertView.findViewById(R.id.deal_img);
       Item item = getItem(position);
       if (item != null) {
          text.setText(item.getTitle());
          new RetrieveImageTask(image).execute(item.getSmallPicUrl());
       }
       return convertView;
    }
}
Watch out for leaks
public class LeakProofActivity extends Activity {
   LeakProofAsyncTask task;
   private class LeakProofAsyncTask extends AsyncTask<String, Void, Bitmap>{
      Context potentialLeak = LeakProofActivity.this;

      @Override
      protected Bitmap doInBackground(String... arg0) {
         // Do something that takes a long time
         // Note if you need a Context here, use Application
         return null;
      }

      @Override
      protected void onPostExecute(Bitmap result){
         // update UI, etc.
      }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

      task = (LeakProofAsyncTask) getLastNonConfigurationInstance();
      if (task != null){
         task.potentialLeak = this;
      }
    }
    @Override
    protected void onDestroy() {
       super.onDestroy();
       if (task != null){
          task.potentialLeak = null;
       }
    }
    @Override
    public Object onRetainNonConfigurationInstance() {
       return task;
    }
}
How to build a cache?

• WeakReferences?
• SoftReferences?
• WeakHashMap?
• MapMaker?
LinkedHashMap!?
private static class ImageCache extends LinkedHashMap<String, Bitmap>{

    private final int capacity;

    public ImageCache(int capacity){
        super(capacity/2, 0.75f, true);
        this.capacity = capacity;
    }

    @Override
    protected boolean removeEldestEntry(Entry<String, Bitmap> eldest) {
        return this.size() > capacity;
    }
}
Disk Cache

• Context.getCacheDir()
• SQLite
• Environment.getExternalStorage()
Sidebar: Bitmaps & Heap
Reported by andreas....@googlemail.com, May 22, 2010
Note: This is NOT a requst for assistance!

In my applications, I keep getting the following exception:

E/AndroidRuntime( 1420): java.lang.OutOfMemoryError: bitmap size exceeds
VM budget
E/AndroidRuntime( 1420): 
 at
android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
E/AndroidRuntime( 1420): 
 at
android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:459)
E/AndroidRuntime( 1420): 
 at
android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:515)
E/AndroidRuntime( 1420): 
 at
de.schildbach.bitmapbug.MyActivity.bitmap(MyActivity.java:38)

Comment 1 by romaingu...@gtempaccount.com, May 23, 2010
Your app needs to use less memory.

                       http://code.google.com/p/android/issues/detail?id=8488
Use Placeholders

      ImageView image =
          (ImageView) convertView.findViewById(R.id.deal_img);

      image.setImageBitmap(
          BitmapFactory.decodeResource(
              getResources(), R.drawable.temp));

      Item item = getItem(position);

      new RetrieveImageTask(image).
          execute(item.getSmallPicUrl());
@Override
                       View Holders
public View getView(final int position, View cell, ViewGroup parent) {
	 ViewHolder holder = (ViewHolder) cell.getTag();
	 if (holder == null){
	 	 holder = new ViewHolder(cell);
	 	 cell.setTag(holder);
	 }
	 Bitmap thumb = (Bitmap) getItem(position);
   holder.img.setImageBitmap(thumb);
	 File file = getImageFile(position);
	 if (selectedFiles.contains(file)){
	 	 holder.cbox.setChecked(true);
	 } else {
	 	 holder.cbox.setChecked(false);
	 }
	 return cell;
}

static class ViewHolder {
    final ImageView img;
    final CheckBox cbox;
    ViewHolder(View cell){
        img = (ImageView) cell.findViewById(R.id.thumb);
    	 cbox = (CheckBox) cell.findViewById(R.id.cbox);
    }
}
Sidebar: Strict Mode
CONTENT
PROVIDERS
SQL?


       NoSQL?


           SortOfSQL!
Queries
Cursor cursor = getContentResolver().query(table,
                                           columns,
                                           whereClause,
                                           paramValues,
                                           sortOrder);
while (cursor.moveToNext()){
    // process results
}
cursor.close();
Music
import   static   android.provider.BaseColumns._ID;
import   static   android.provider.MediaStore.Audio.AudioColumns.ARTIST;
import   static   android.provider.MediaStore.Audio.AudioColumns.IS_MUSIC;
import   static   android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
import   static   android.provider.MediaStore.MediaColumns.DATA;
import   static   android.provider.MediaStore.MediaColumns.TITLE;

String[] columns = {TITLE,ARTIST,_ID, DATA};
// where clause so we don't get ringtones, podcasts, etc.
String whereClause = IS_MUSIC + " = ?";
String[] whereValues = {"1"};
cursor = managedQuery(EXTERNAL_CONTENT_URI,
	 columns,
	 whereClause,
	 whereValues,
	 null
);
Contacts
String[] projection = {Phone.CONTACT_ID, Phone.NUMBER};
String selection = Data.IN_VISIBLE_GROUP + "=1 AND " +
    Phone.NUMBER + " LIKE ?";
String[] selectionArgs = {"%" + phoneSubStr + "%"};
Cursor phoneCursor = resolver.query(Phone.CONTENT_URI,
                                 projection,
                                 selection,
                                 selectionArgs,
                                 null);


String[] projection = new String[] {StructuredName.GIVEN_NAME,
                                    StructuredName.FAMILY_NAME,
                                    StructuredName.RAW_CONTACT_ID,
                                    StructuredName.CONTACT_ID};
String selection = StructuredName.CONTACT_ID+ " = ? AND " +
    Data.MIMETYPE + " = '" + StructuredName.CONTENT_ITEM_TYPE +"'";
String[] selectionArgs = new String[] {contact.id};
Cursor nameCursor = resolver.query(Data.CONTENT_URI,
                                projection,
                                selection,
                                selectionArgs,
                                null);
Scanning media
Scanning 101
MediaScannerConnection conn = new MediaScannerConnection(this,
  new MediaScannerConnectionClient(){
    public void onMediaScannerConnected(){
        scanFile("/some/path/SomeSong.mp3", "audio/mpeg3");
        scanFile("/some/other/path/IMG1999.jpg", "image/jpeg");
    }

      public void onScanCompleted(String path, Uri uri){
          Log.d("LogTag", "Media scanned uir=" + uri.toString());
      }
});

conn.connect();
Cursor   Adapter
CursorAdapter
Avoid
Use Other Apps
private static final int SELECT_VIDEO = 1;
private Uri videoUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
    Button vidBtn = (Button) findViewById(R.id.vidBtn);
    vidBtn.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View button) {
            Intent videoChooser = new Intent(Intent.ACTION_GET_CONTENT);
            videoChooser.setType("video/*");
            startActivityForResult(videoChooser, SELECT_VIDEO);
        }
    });
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
        Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == SELECT_VIDEO && resultCode == RESULT_OK){
        videoUri = data.getData();
    }
}
ANIMATION
Dissolve Animation
private void nextSlide() {
    AlphaAnimation animation = new AlphaAnimation(0.0f, 1.0f);
    if ((count % 2) == 0) {
        animation = new AlphaAnimation(1.0f, 0.0f);
    }
    animation.setStartOffset(TIME_PER_SLIDE);
    animation.setDuration(TIME_PER_SLIDE);
    animation.setFillAfter(true);
    animation.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {}
        @Override
        public void onAnimationRepeat(Animation animation) {}
        @Override
        public void onAnimationEnd(Animation animation) {
            if (playingSlides){
                nextImage = getNextImage();
                ImageView backgroundImage =
                    (count % 2 == 0) ? rightSlide : leftSlide;
                backgroundImage.setImageBitmap(nextImage);
                count++;
                nextSlide();
            }
        }
    });
    rightSlide.startAnimation(animation);
    currentImage = nextImage;
}
Honeycomb+
Animators
ImageView backgroundImage = (count % 2 == 0) ? rightSlide : leftSlide;
ObjectAnimator anim =
    ObjectAnimator.ofFloat(backgroundImage, "alpha", 0.0f, 1.0f);
anim.addListener(new AnimatorListenerAdapter(){
    public void onAnimationEnd(Animator animator){
        nextSlide();
    }
});
A/V
PLAYBACK
playBtn.setOnClickListener(new OnClickListener(){
    private Handler handler = new Handler();
    MediaPlayer player = null;
    long maxTime = 15L*1000; // 15 seconds
    long timeLeft = maxTime;
                                                      Audio Preview
    Runnable autoStop;
    @Override
    public void onClick(View view) {
        if (player == null){
            player = MediaPlayer.create(activity, song.uri);
        }
        if (!playingSongs.contains(song.id)){           Start/Resume
            player.start();
            playingSongs.add(song.id);
            autoStop = new Runnable(){
                                                     Timer
                 @Override
                 public void run() {
                     player.pause();
                     player.seekTo(0);
                     playingSongs.remove(song.id);
                     playBtn.setText(R.string.play);
                     timeLeft = maxTime;
                }
            };
            handler.postDelayed(autoStop, timeLeft);
            playBtn.setText(R.string.pause);
        } else {
            player.pause();
                                                                   Pause
            playingSongs.remove(song.id);
            timeLeft = maxTime - player.getCurrentPosition();
            playBtn.setText(R.string.play);
                                                                Calc time left
            handler.removeCallbacks(autoStop);
        }
    }
});
Handler?
Handler?
Pipeline Thread
Looper.prepare();
handler = new Handler();

// handle tasks in queue



Looper.loop();
Handler?
      Thread                 Pipeline Thread
                             Looper.prepare();
                             handler = new Handler();

                             // handle tasks in queue



                             Looper.loop();

// long running task
Message msg =
  handler.obtainMessage();
handler.sendMessage(msg);
Handler?
      Thread                 Pipeline Thread                 Thread
                             Looper.prepare();
                             handler = new Handler();

                             // handle tasks in queue
                                                        // long running task
                                                        handler.post(
                             Looper.loop();                 new Runnable() {...
                                                        });
// long running task
Message msg =
  handler.obtainMessage();
handler.sendMessage(msg);
Theme Muzak
private MediaPlayer player;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setupThemeMusic();
}

@Override
public void onResume() {
    super.onResume();
    if (player != null){
        player.start();
    }
                                               @Override
}
                                               public void onPause(){
                                                   super.onPause();
                                                   if (player != null && player.isPlaying()){
                                                       player.pause();
                                                   }
                                               }

                                               @Override
                                               protected void onDestroy() {
                                                   super.onDestroy();
                                                   if (player != null && player.isPlaying()){
                                                       player.stop();
                                                   }
                                                   player.release();
                                               }
Activity Lifecycle
Video Playback
Uri videoUri = ...;

VideoView video = (VideoView) findViewById(R.id.video);
video.setVideoURI(videoUri);

MediaController controller = new MediaController(this);
controller.setMediaPlayer(video);
video.setMediaController(controller);
video.requestFocus();
video.start();
TAKE A
PICTURE
Use the Camera (app)
import static android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
photoUri = getContentResolver().insert(
        EXTERNAL_CONTENT_URI, new ContentValues());
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent,TAKE_PHOTO);




@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == Activity.RESULT_OK && requestCode == TAKE_PHOTO){
        ImageView img = (ImageView) findViewById(R.id.photoThumb);
        InputStream stream =
            getContentResolver().openInputStream(photoUri);
        Bitmap bmp = BitmapFactory.decodeStream(stream);
        img.setImageBitmap(bmp);
    }
}
EXIF!
Popular on Facebook
Correctly Oriented
Options photoImageOptions = new BitmapFactory.Options();
Matrix matrix = new Matrix();
ExifInterface ei = new ExifInterface(somePath);
int orientation = ei.getAttributeInt(TAG_ORIENTATION, ORIENTATION_UNDEFINED);
int angle = 0;
switch (orientation) {
    case ORIENTATION_ROTATE_90 : angle=90; break;
    case ORIENTATION_ROTATE_180 : angle=180; break;
    case ORIENTATION_ROTATE_270 : angle=270; break;
    default: break;
}
Bitmap bm = BitmapFactory.decodeFile(path, photoImageOptions);
if (angle > 0){
    matrix.setRotate(angle);
    Bitmap bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(),
                                    matrix, true);
}
Geo Tagging


ExifInterface exif = new ExifInterface(filename);
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, latitude);
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, longitude);
exif.saveAttributes();




                                                    “dd/1,mm/1,ss/1”
Where?
Getting a (geo) fix

LocationManager mgr = getSystemService(LOCATION_SERVICE);

for (String provider : mgr.getAllProviders()){
    Location last = mgr.getLastKnownLocation(last);

    mgr.requestLocationUpdates(provider, 60000, 500, new LocationListener(){
        public void onLocationChanged(Location loc){
            // do stuff
        }
        // other methods
    });
}
To the cloud!
Uploading a photo

String url = "http://my/server";
HttpClient client = new DefaultHttpClient();
HttpContext context = new BasicHttpContext();
HttpPost post = new HttpPost(url);

File imgFile = new File("/path/to/my/image");
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
entity.addPart("image", new FileBody(imgFile));
post.setEntity(entity);

HttpResponse response = client.execute(httpPost, localContext);
Upload Service
UploadService extends IntentService {

    protected void onHandleIntent(Intent i){
        String imgPath = i.getStringExtra("file");
        // upload code goes here
    }
}




Intent i = new Intent(this, UploadService.class);
i.putExtra("file", "/path/to/my/image");
startService(i);
Process Priority
       Foreground

         Visible


         Service

       Background
         Empty
A/V
RECORDING
Video Preview
private   SurfaceHolder holder;
private   Camera camera;
private   MediaRecorder mediaRecorder;
private   File tempFile;
private   SurfaceView preview;
private   boolean isRecording = false;
private   final int maxDurationInMs = 20000;
private   final long maxFileSizeInBytes = 500000;
private   final int videoFramesPerSecond = 20;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    preview = new SurfaceView(this);
    holder = preview.getHolder();
    holder.addCallback(cameraman);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    setContentView(preview);
    tempFile = new File(getCacheDir(), "temp.mov");
    if (tempFile.length() > 0){
        tempFile.delete();
    }
}
Video Preview
private Callback cameraman = new Callback(){
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        camera = Camera.open();
        camera.setPreviewDisplay(holder);
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format,
            int width,int height) {
        Parameters params = camera.getParameters();
        List<Size> sizes = params.getSupportedPreviewSizes();
        Size optimalSize = getOptimalPreviewSize(sizes, width, height);
        params.setPreviewSize(optimalSize.width, optimalSize.height);
        camera.setParameters(params);
        camera.startPreview();
    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        camera.stopPreview();
        camera.release();
    }
};
Video Preview
private void startRecording(){
    if (isRecording){
        return;
    }
    isRecording = true;
    camera.unlock();
    mediaRecorder = new MediaRecorder();
    mediaRecorder.setCamera(camera);
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
    mediaRecorder.setMaxDuration(maxDurationInMs);

    mediaRecorder.setOutputFile(tempFile.getPath());
    mediaRecorder.setVideoFrameRate(videoFramesPerSecond);
    mediaRecorder.setVideoSize(preview.getWidth(), preview.getHeight());
    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
    mediaRecorder.setPreviewDisplay(holder.getSurface());
    mediaRecorder.setMaxFileSize(maxFileSizeInBytes);

    mediaRecorder.prepare();
    mediaRecorder.start();
}

Weitere ähnliche Inhalte

Was ist angesagt?

CompletableFuture
CompletableFutureCompletableFuture
CompletableFuturekoji lin
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Ontico
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best PracticesYekmer Simsek
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projectsIgnacio Martín
 
Google Fit, Android Wear & Xamarin
Google Fit, Android Wear & XamarinGoogle Fit, Android Wear & Xamarin
Google Fit, Android Wear & XamarinPeter Friese
 
The redux saga begins
The redux saga beginsThe redux saga begins
The redux saga beginsDaniel Franz
 
Under the Hood: Using Spring in Grails
Under the Hood: Using Spring in GrailsUnder the Hood: Using Spring in Grails
Under the Hood: Using Spring in GrailsGR8Conf
 
Under the Hood: Using Spring in Grails
Under the Hood: Using Spring in GrailsUnder the Hood: Using Spring in Grails
Under the Hood: Using Spring in GrailsBurt Beckwith
 
망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19종인 전
 
【Unite 2017 Tokyo】もっと気軽に、動的なコンテンツ配信を ~アセットバンドルの未来と開発ロードマップ
【Unite 2017 Tokyo】もっと気軽に、動的なコンテンツ配信を ~アセットバンドルの未来と開発ロードマップ【Unite 2017 Tokyo】もっと気軽に、動的なコンテンツ配信を ~アセットバンドルの未来と開発ロードマップ
【Unite 2017 Tokyo】もっと気軽に、動的なコンテンツ配信を ~アセットバンドルの未来と開発ロードマップUnite2017Tokyo
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsPiotr Pelczar
 
Programming with ZooKeeper - A basic tutorial
Programming with ZooKeeper - A basic tutorialProgramming with ZooKeeper - A basic tutorial
Programming with ZooKeeper - A basic tutorialJeff Smith
 
Event driven javascript
Event driven javascriptEvent driven javascript
Event driven javascriptFrancesca1980
 
G*なクラウド 雲のかなたに ショートバージョン
G*なクラウド 雲のかなたに ショートバージョンG*なクラウド 雲のかなたに ショートバージョン
G*なクラウド 雲のかなたに ショートバージョンTsuyoshi Yamamoto
 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionChristian Panadero
 

Was ist angesagt? (19)

CompletableFuture
CompletableFutureCompletableFuture
CompletableFuture
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
 
Rxjs marble-testing
Rxjs marble-testingRxjs marble-testing
Rxjs marble-testing
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
 
Physical web
Physical webPhysical web
Physical web
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projects
 
Angular mix chrisnoring
Angular mix chrisnoringAngular mix chrisnoring
Angular mix chrisnoring
 
Google Fit, Android Wear & Xamarin
Google Fit, Android Wear & XamarinGoogle Fit, Android Wear & Xamarin
Google Fit, Android Wear & Xamarin
 
The redux saga begins
The redux saga beginsThe redux saga begins
The redux saga begins
 
Under the Hood: Using Spring in Grails
Under the Hood: Using Spring in GrailsUnder the Hood: Using Spring in Grails
Under the Hood: Using Spring in Grails
 
Under the Hood: Using Spring in Grails
Under the Hood: Using Spring in GrailsUnder the Hood: Using Spring in Grails
Under the Hood: Using Spring in Grails
 
망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19
 
【Unite 2017 Tokyo】もっと気軽に、動的なコンテンツ配信を ~アセットバンドルの未来と開発ロードマップ
【Unite 2017 Tokyo】もっと気軽に、動的なコンテンツ配信を ~アセットバンドルの未来と開発ロードマップ【Unite 2017 Tokyo】もっと気軽に、動的なコンテンツ配信を ~アセットバンドルの未来と開発ロードマップ
【Unite 2017 Tokyo】もっと気軽に、動的なコンテンツ配信を ~アセットバンドルの未来と開発ロードマップ
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.js
 
Programming with ZooKeeper - A basic tutorial
Programming with ZooKeeper - A basic tutorialProgramming with ZooKeeper - A basic tutorial
Programming with ZooKeeper - A basic tutorial
 
Event driven javascript
Event driven javascriptEvent driven javascript
Event driven javascript
 
Firebase ng2 zurich
Firebase ng2 zurichFirebase ng2 zurich
Firebase ng2 zurich
 
G*なクラウド 雲のかなたに ショートバージョン
G*なクラウド 雲のかなたに ショートバージョンG*なクラウド 雲のかなたに ショートバージョン
G*なクラウド 雲のかなたに ショートバージョン
 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca edition
 

Andere mochten auch

Unmanned Eyes In The Commercial Skies Presentation
Unmanned Eyes In The Commercial Skies PresentationUnmanned Eyes In The Commercial Skies Presentation
Unmanned Eyes In The Commercial Skies Presentationmseraj
 
Jisc RSC Wales ISS 260213
Jisc RSC Wales ISS 260213Jisc RSC Wales ISS 260213
Jisc RSC Wales ISS 260213Lis Parcell
 
The socio political culture and economy of the thirteen american colonies
The socio political culture and economy of the thirteen american coloniesThe socio political culture and economy of the thirteen american colonies
The socio political culture and economy of the thirteen american coloniesPaulo Arieu
 
Mis 2 Princesas Chico 2
Mis 2 Princesas Chico 2Mis 2 Princesas Chico 2
Mis 2 Princesas Chico 2Carlos Arrieta
 
Overview for Technical Nearshore Investment in Costa Rica
Overview for Technical Nearshore Investment in Costa RicaOverview for Technical Nearshore Investment in Costa Rica
Overview for Technical Nearshore Investment in Costa RicaAndrea Tanzi
 
Presentation of the SIG TEL 4 Health
Presentation of the SIG TEL 4 HealthPresentation of the SIG TEL 4 Health
Presentation of the SIG TEL 4 HealthHendrik Drachsler
 
Digital literacy and competences as essential life skills
Digital literacy and competences as essential life skillsDigital literacy and competences as essential life skills
Digital literacy and competences as essential life skillsDeborahJane
 
Virtuous Spiral or Vicious Circle?
Virtuous Spiral or Vicious Circle?Virtuous Spiral or Vicious Circle?
Virtuous Spiral or Vicious Circle?Martin Rehm
 
Open Access Week | Dag van het onderzoek
Open Access Week | Dag van het onderzoekOpen Access Week | Dag van het onderzoek
Open Access Week | Dag van het onderzoekHendrik Drachsler
 
An API-first approach. Integrating ckan with RDM services
An API-first approach. Integrating ckan with RDM servicesAn API-first approach. Integrating ckan with RDM services
An API-first approach. Integrating ckan with RDM servicesJoss Winn
 
Rik Panganiban's Keynote at SLCC 2011
Rik Panganiban's Keynote at SLCC 2011Rik Panganiban's Keynote at SLCC 2011
Rik Panganiban's Keynote at SLCC 2011rik panganiban
 
Szablon strony www
Szablon strony wwwSzablon strony www
Szablon strony wwwMaria Ptak
 
Lift'11 Venture Night Presentation
Lift'11 Venture Night PresentationLift'11 Venture Night Presentation
Lift'11 Venture Night PresentationSebastien Dubuis
 
Riks tips on giving great presentations
Riks tips on giving great presentationsRiks tips on giving great presentations
Riks tips on giving great presentationsrik panganiban
 
Digital literacies supporting learning
Digital literacies supporting learningDigital literacies supporting learning
Digital literacies supporting learningLis Parcell
 

Andere mochten auch (20)

Unmanned Eyes In The Commercial Skies Presentation
Unmanned Eyes In The Commercial Skies PresentationUnmanned Eyes In The Commercial Skies Presentation
Unmanned Eyes In The Commercial Skies Presentation
 
Jisc RSC Wales ISS 260213
Jisc RSC Wales ISS 260213Jisc RSC Wales ISS 260213
Jisc RSC Wales ISS 260213
 
Chemistryfm
ChemistryfmChemistryfm
Chemistryfm
 
The socio political culture and economy of the thirteen american colonies
The socio political culture and economy of the thirteen american coloniesThe socio political culture and economy of the thirteen american colonies
The socio political culture and economy of the thirteen american colonies
 
Mis 2 Princesas Chico 2
Mis 2 Princesas Chico 2Mis 2 Princesas Chico 2
Mis 2 Princesas Chico 2
 
Overview for Technical Nearshore Investment in Costa Rica
Overview for Technical Nearshore Investment in Costa RicaOverview for Technical Nearshore Investment in Costa Rica
Overview for Technical Nearshore Investment in Costa Rica
 
Presentation of the SIG TEL 4 Health
Presentation of the SIG TEL 4 HealthPresentation of the SIG TEL 4 Health
Presentation of the SIG TEL 4 Health
 
Digital literacy and competences as essential life skills
Digital literacy and competences as essential life skillsDigital literacy and competences as essential life skills
Digital literacy and competences as essential life skills
 
Virtuous Spiral or Vicious Circle?
Virtuous Spiral or Vicious Circle?Virtuous Spiral or Vicious Circle?
Virtuous Spiral or Vicious Circle?
 
Open Access Week | Dag van het onderzoek
Open Access Week | Dag van het onderzoekOpen Access Week | Dag van het onderzoek
Open Access Week | Dag van het onderzoek
 
An API-first approach. Integrating ckan with RDM services
An API-first approach. Integrating ckan with RDM servicesAn API-first approach. Integrating ckan with RDM services
An API-first approach. Integrating ckan with RDM services
 
Pero florecera
Pero floreceraPero florecera
Pero florecera
 
Rik Panganiban's Keynote at SLCC 2011
Rik Panganiban's Keynote at SLCC 2011Rik Panganiban's Keynote at SLCC 2011
Rik Panganiban's Keynote at SLCC 2011
 
Miejsca opuszczone
Miejsca opuszczoneMiejsca opuszczone
Miejsca opuszczone
 
Szablon strony www
Szablon strony wwwSzablon strony www
Szablon strony www
 
Lift'11 Venture Night Presentation
Lift'11 Venture Night PresentationLift'11 Venture Night Presentation
Lift'11 Venture Night Presentation
 
Mobile Web 5.0
Mobile Web 5.0Mobile Web 5.0
Mobile Web 5.0
 
Riks tips on giving great presentations
Riks tips on giving great presentationsRiks tips on giving great presentations
Riks tips on giving great presentations
 
30 wcwb
30 wcwb30 wcwb
30 wcwb
 
Digital literacies supporting learning
Digital literacies supporting learningDigital literacies supporting learning
Digital literacies supporting learning
 

Ähnlich wie Android workshop

Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Alfredo Morresi
 
Capture image on eye blink
Capture image on eye blinkCapture image on eye blink
Capture image on eye blinkInnovationM
 
Android programming -_pushing_the_limits
Android programming -_pushing_the_limitsAndroid programming -_pushing_the_limits
Android programming -_pushing_the_limitsDroidcon Berlin
 
Oleksandr Tolstykh
Oleksandr TolstykhOleksandr Tolstykh
Oleksandr TolstykhCodeFest
 
Improving android experience for both users and developers
Improving android experience for both users and developersImproving android experience for both users and developers
Improving android experience for both users and developersPavel Lahoda
 
Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon Berlin
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android InfrastructureAlexey Buzdin
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android InfrastructureC.T.Co
 
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...Publicis Sapient Engineering
 
Androidaop 170105090257
Androidaop 170105090257Androidaop 170105090257
Androidaop 170105090257newegg
 
Modern Android app library stack
Modern Android app library stackModern Android app library stack
Modern Android app library stackTomáš Kypta
 
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012Amazon Web Services
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleThierry Wasylczenko
 
Build Lightweight Web Module
Build Lightweight Web ModuleBuild Lightweight Web Module
Build Lightweight Web ModuleMorgan Cheng
 
Non Conventional Android Programming (English)
Non Conventional Android Programming (English)Non Conventional Android Programming (English)
Non Conventional Android Programming (English)Davide Cerbo
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming Enguest9bcef2f
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Tsuyoshi Yamamoto
 

Ähnlich wie Android workshop (20)

Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)
 
From newbie to ...
From newbie to ...From newbie to ...
From newbie to ...
 
Capture image on eye blink
Capture image on eye blinkCapture image on eye blink
Capture image on eye blink
 
Android programming -_pushing_the_limits
Android programming -_pushing_the_limitsAndroid programming -_pushing_the_limits
Android programming -_pushing_the_limits
 
Oleksandr Tolstykh
Oleksandr TolstykhOleksandr Tolstykh
Oleksandr Tolstykh
 
Improving android experience for both users and developers
Improving android experience for both users and developersImproving android experience for both users and developers
Improving android experience for both users and developers
 
Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahoda
 
Android - Api & Debugging in Android
Android - Api & Debugging in AndroidAndroid - Api & Debugging in Android
Android - Api & Debugging in Android
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...
XebiCon'17 : Faites chauffer les neurones de votre Smartphone avec du Deep Le...
 
Androidaop 170105090257
Androidaop 170105090257Androidaop 170105090257
Androidaop 170105090257
 
Modern Android app library stack
Modern Android app library stackModern Android app library stack
Modern Android app library stack
 
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
 
Android For All The Things
Android For All The ThingsAndroid For All The Things
Android For All The Things
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
 
Build Lightweight Web Module
Build Lightweight Web ModuleBuild Lightweight Web Module
Build Lightweight Web Module
 
Non Conventional Android Programming (English)
Non Conventional Android Programming (English)Non Conventional Android Programming (English)
Non Conventional Android Programming (English)
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
 

Mehr von Michael Galpin

Android lessons you won't learn in school
Android lessons you won't learn in schoolAndroid lessons you won't learn in school
Android lessons you won't learn in schoolMichael Galpin
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesMichael Galpin
 
Scala on Android: Experiences at Bump Technologies
Scala on Android: Experiences at Bump TechnologiesScala on Android: Experiences at Bump Technologies
Scala on Android: Experiences at Bump TechnologiesMichael Galpin
 
That’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your BatteryThat’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your BatteryMichael Galpin
 
Persistent Data Structures And Managed References
Persistent Data Structures And Managed ReferencesPersistent Data Structures And Managed References
Persistent Data Structures And Managed ReferencesMichael Galpin
 
Mobile Development 101
Mobile Development 101Mobile Development 101
Mobile Development 101Michael Galpin
 
RIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWTRIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWTMichael Galpin
 
Introduction to Scala for Java Developers
Introduction to Scala for Java DevelopersIntroduction to Scala for Java Developers
Introduction to Scala for Java DevelopersMichael Galpin
 

Mehr von Michael Galpin (11)

Android lessons you won't learn in school
Android lessons you won't learn in schoolAndroid lessons you won't learn in school
Android lessons you won't learn in school
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and Smartphones
 
Scala on Android: Experiences at Bump Technologies
Scala on Android: Experiences at Bump TechnologiesScala on Android: Experiences at Bump Technologies
Scala on Android: Experiences at Bump Technologies
 
That’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your BatteryThat’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your Battery
 
Persistent Data Structures And Managed References
Persistent Data Structures And Managed ReferencesPersistent Data Structures And Managed References
Persistent Data Structures And Managed References
 
Scala on Your Phone
Scala on Your PhoneScala on Your Phone
Scala on Your Phone
 
Mobile Development 101
Mobile Development 101Mobile Development 101
Mobile Development 101
 
RIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWTRIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWT
 
Eclipse @eBay 2009
Eclipse @eBay 2009Eclipse @eBay 2009
Eclipse @eBay 2009
 
Introduction to Scala for Java Developers
Introduction to Scala for Java DevelopersIntroduction to Scala for Java Developers
Introduction to Scala for Java Developers
 
Eclipse@eBay
Eclipse@eBayEclipse@eBay
Eclipse@eBay
 

Kürzlich hochgeladen

Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 

Kürzlich hochgeladen (20)

Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 

Android workshop

  • 2. ABOUT: ME ‣ Android engineer, Bump Technologies ‣ ex-eBay: eBay Mobile for Android ‣ Android in Practice ‣ Social info ‣ @michaelg ‣ +Michael Galpin
  • 3. Bump Technologies • Creators of Bump app • Android + iOS • 65M+ Downloads • Creators of BumpCube • Hiring!
  • 4. You down with AIP? • Chapter 11: “Appeal to the senses using multimedia.” • Slideshow app MediaMogul.apk • http:// code.google.com/p/ android-in-practice/
  • 5.
  • 7. “Of all of our inventions for mass communication, pictures still speak the most universally understood language.” -- Walt Disney
  • 8.
  • 9.
  • 10.
  • 11.
  • 13.
  • 14. AndroidManifest.xml <uses-feature android:name="android.hardware.camera" android:required="true" /> <uses-feature android:name="android.hardware.camera.autofocus" android:required="true"/> <uses-feature android:name="android.hardware.camera.flash" android:required="false" /> <uses-feature android:name="android.hardware.camera.front" android:required="false" /> <uses-feature android:name="android.hardware.microphone" android:required="true"/> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
  • 15. Check the front private boolean hasFrontFacingCamera(){ PackageManager mgr = this.getPackageManager(); for (FeatureInfo fi : mgr.getSystemAvailableFeatures()){ if (fi.name.equals(PackageManager.FEATURE_CAMERA_FRONT)){ return true; } } return false; } private Camera getFrontFacingCamera(){ for (int i=0;i<Camera.getNumberOfCameras();i++){ Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(i, info); if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){ return Camera.open(i); } } return null; }
  • 16. Check the front private boolean hasFrontFacingCamera(){ PackageManager mgr = this.getPackageManager(); for (FeatureInfo fi : mgr.getSystemAvailableFeatures()){ if (fi.name.equals(PackageManager.FEATURE_CAMERA_FRONT)){ return true; } } return false; } private Camera getFrontFacingCamera(){ for (int i=0;i<Camera.getNumberOfCameras();i++){ Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(i, info); if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){ return Camera.open(i); } } return null; }
  • 17. But I have to support Android 2.1
  • 18.
  • 19.
  • 21. LOLZ // Can't use Build.VERSION_CODES.GINGERBREAD if (Build.VERSION.SDK_INT >= 9){ PostFroyoClass wontThisBlowUp = new PostFroyoClass(); }
  • 22. These are my customers!
  • 23. These are my customers!
  • 24. Proprietary APIs FTW! import com.sprint.hardware.twinCamDevice.FrontFacingCamera; Camera evoCam = FrontFacingCamera.getFrontFacingCamera();
  • 26.
  • 30. MediaPlayer.framework? [MPMusicPlayerController iPodMusicPlayer] ?? [MusicLibrary sharedMusicLibrary] ??? UIImagePickerController ?
  • 31. MediaPlayer.framework? [MPMusicPlayerController iPodMusicPlayer] ?? [MusicLibrary sharedMusicLibrary] ??? UIImagePickerController ?
  • 32. MediaPlayer.framework? [MPMusicPlayerController iPodMusicPlayer] ?? [MusicLibrary sharedMusicLibrary] ??? UIImagePickerController ? Files !!!!
  • 33. Inside your APK External
  • 34. Just give it to me /res/raw Resources res = this.getResources(); InputStream stream = res.openRawResource(R.raw.sunflower); MediaPlayer.create(this, R.raw.constancy).start();
  • 35. I like big / assets and I cannot lie
  • 36. MediaPlayer player = new MediaPlayer(); AssetManager mgr = getResources().getAssets(); String audioDir = "audio"; final LinkedList<FileDescriptor> queue = new LinkedList<FileDescriptor>(); for (String song : mgr.list("audio")){ queue.add( mgr.openFd(audioDir + "/" + song).getFileDescriptor()); } if (!queue.isEmpty()){ FileDescriptor song = queue.poll(); player.setDataSource(song); player.prepare(); player.start(); } player.setOnCompletionListener(new OnCompletionListener(){ @Override public void onCompletion(MediaPlayer mp) { if (!queue.isEmpty()){ FileDescriptor song = queue.poll(); player.setDataSource(song); player.prepare(); player.start(); } } });
  • 37.
  • 38. File picturesDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES);
  • 39. File picturesDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES);
  • 41.
  • 42. Loading local images InputStream stream = new FileInputStream(imgFile); Bitmap bm = BitmapFactory.decodeStream(stream);
  • 43. Loading local images InputStream stream = new FileInputStream(imgFile); Bitmap bm = BitmapFactory.decodeStream(stream); // calculate desired width and height Bitmap thumb = ThumbnailUtils.extractThumbnail(bm, width, height); Bitmap thumb = Bitmap.createScaledBitmap(bm, width, height, false);
  • 44.
  • 45. Loading without exploding public static Bitmap decodeDownsizedBitmapStream(File file, int target, Context context) throws IOException { FileInputStream stream = new FileInputStream(file); Pair<Integer, Integer> source = getDimensionsForStream(stream); stream.close(); FileInputStream in = new FileInputStream(file); Options options = new Options(); options.inSampleSize = 1 + getDownSampleSize(max(source.first, source.second), target); return BitmapFactory.decodeStream(in, null, options); } public static Pair<Integer, Integer> getDimensionsForStream(InputStream in){ Options options = new Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, options); return new Pair<Integer, Integer>(options.outWidth, options.outHeight); } public static int getDownSampleSize(int source, int target){ int size = 1; if (source <= 2*target){ int power = (int) ((log (source / target)) / log(2)); size = (int) pow(2, power); } return size; }
  • 46. Loading web images URL url = new URL(urlString); // NOTE, be careful about just doing "url.openStream()" // it's a shortcut for openConnection().getInputStream() and doesn't set timeouts // the defaults are "infinite" so it will wait forever if endpoint server is down // do it properly with a few more lines of code . . . URLConnection conn = url.openConnection(); conn.setConnectTimeout(3000); conn.setReadTimeout(5000); Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream());
  • 47.
  • 48. AsyncTask FTW! private class RetrieveImageTask extends AsyncTask<String, Void, Bitmap> { private ImageView imageView; public RetrieveImageTask(ImageView imageView) { this.imageView = imageView; } @Override protected Bitmap doInBackground(String... args) { try { URL url = new URL(args[0]); URLConnection conn = url.openConnection(); conn.setConnectTimeout(3000); conn.setReadTimeout(5000); return BitmapFactory.decodeStream(conn.getInputStream()); } catch (Exception e) { } return null; } @Override protected void onPostExecute(Bitmap bitmap) { if (bitmap != null) { imageView.setImageBitmap(bitmap); } } }
  • 49. Loading a dozen images isn’t cool. Y’know what’s cool? Loading a billion images.
  • 50. Hot or Not? private class DealsAdapter extends ArrayAdapter<Item> { @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.list_item, parent, false); } TextView text = (TextView) convertView.findViewById(R.id.deal_title); ImageView image = (ImageView) convertView.findViewById(R.id.deal_img); Item item = getItem(position); if (item != null) { text.setText(item.getTitle()); new RetrieveImageTask(image).execute(item.getSmallPicUrl()); } return convertView; } }
  • 51. Watch out for leaks public class LeakProofActivity extends Activity { LeakProofAsyncTask task; private class LeakProofAsyncTask extends AsyncTask<String, Void, Bitmap>{ Context potentialLeak = LeakProofActivity.this; @Override protected Bitmap doInBackground(String... arg0) { // Do something that takes a long time // Note if you need a Context here, use Application return null; } @Override protected void onPostExecute(Bitmap result){ // update UI, etc. } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); task = (LeakProofAsyncTask) getLastNonConfigurationInstance(); if (task != null){ task.potentialLeak = this; } } @Override protected void onDestroy() { super.onDestroy(); if (task != null){ task.potentialLeak = null; } } @Override public Object onRetainNonConfigurationInstance() { return task; } }
  • 52.
  • 53. How to build a cache? • WeakReferences? • SoftReferences? • WeakHashMap? • MapMaker?
  • 54. LinkedHashMap!? private static class ImageCache extends LinkedHashMap<String, Bitmap>{ private final int capacity; public ImageCache(int capacity){ super(capacity/2, 0.75f, true); this.capacity = capacity; } @Override protected boolean removeEldestEntry(Entry<String, Bitmap> eldest) { return this.size() > capacity; } }
  • 55. Disk Cache • Context.getCacheDir() • SQLite • Environment.getExternalStorage()
  • 56. Sidebar: Bitmaps & Heap Reported by andreas....@googlemail.com, May 22, 2010 Note: This is NOT a requst for assistance! In my applications, I keep getting the following exception: E/AndroidRuntime( 1420): java.lang.OutOfMemoryError: bitmap size exceeds VM budget E/AndroidRuntime( 1420): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) E/AndroidRuntime( 1420): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:459) E/AndroidRuntime( 1420): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:515) E/AndroidRuntime( 1420): at de.schildbach.bitmapbug.MyActivity.bitmap(MyActivity.java:38) Comment 1 by romaingu...@gtempaccount.com, May 23, 2010 Your app needs to use less memory. http://code.google.com/p/android/issues/detail?id=8488
  • 57.
  • 58. Use Placeholders ImageView image = (ImageView) convertView.findViewById(R.id.deal_img); image.setImageBitmap( BitmapFactory.decodeResource( getResources(), R.drawable.temp)); Item item = getItem(position); new RetrieveImageTask(image). execute(item.getSmallPicUrl());
  • 59. @Override View Holders public View getView(final int position, View cell, ViewGroup parent) { ViewHolder holder = (ViewHolder) cell.getTag(); if (holder == null){ holder = new ViewHolder(cell); cell.setTag(holder); } Bitmap thumb = (Bitmap) getItem(position); holder.img.setImageBitmap(thumb); File file = getImageFile(position); if (selectedFiles.contains(file)){ holder.cbox.setChecked(true); } else { holder.cbox.setChecked(false); } return cell; } static class ViewHolder { final ImageView img; final CheckBox cbox; ViewHolder(View cell){ img = (ImageView) cell.findViewById(R.id.thumb); cbox = (CheckBox) cell.findViewById(R.id.cbox); } }
  • 62. SQL? NoSQL? SortOfSQL!
  • 63. Queries Cursor cursor = getContentResolver().query(table, columns, whereClause, paramValues, sortOrder); while (cursor.moveToNext()){ // process results } cursor.close();
  • 64. Music import static android.provider.BaseColumns._ID; import static android.provider.MediaStore.Audio.AudioColumns.ARTIST; import static android.provider.MediaStore.Audio.AudioColumns.IS_MUSIC; import static android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; import static android.provider.MediaStore.MediaColumns.DATA; import static android.provider.MediaStore.MediaColumns.TITLE; String[] columns = {TITLE,ARTIST,_ID, DATA}; // where clause so we don't get ringtones, podcasts, etc. String whereClause = IS_MUSIC + " = ?"; String[] whereValues = {"1"}; cursor = managedQuery(EXTERNAL_CONTENT_URI, columns, whereClause, whereValues, null );
  • 65. Contacts String[] projection = {Phone.CONTACT_ID, Phone.NUMBER}; String selection = Data.IN_VISIBLE_GROUP + "=1 AND " + Phone.NUMBER + " LIKE ?"; String[] selectionArgs = {"%" + phoneSubStr + "%"}; Cursor phoneCursor = resolver.query(Phone.CONTENT_URI, projection, selection, selectionArgs, null); String[] projection = new String[] {StructuredName.GIVEN_NAME, StructuredName.FAMILY_NAME, StructuredName.RAW_CONTACT_ID, StructuredName.CONTACT_ID}; String selection = StructuredName.CONTACT_ID+ " = ? AND " + Data.MIMETYPE + " = '" + StructuredName.CONTENT_ITEM_TYPE +"'"; String[] selectionArgs = new String[] {contact.id}; Cursor nameCursor = resolver.query(Data.CONTENT_URI, projection, selection, selectionArgs, null);
  • 66.
  • 68. Scanning 101 MediaScannerConnection conn = new MediaScannerConnection(this, new MediaScannerConnectionClient(){ public void onMediaScannerConnected(){ scanFile("/some/path/SomeSong.mp3", "audio/mpeg3"); scanFile("/some/other/path/IMG1999.jpg", "image/jpeg"); } public void onScanCompleted(String path, Uri uri){ Log.d("LogTag", "Media scanned uir=" + uri.toString()); } }); conn.connect();
  • 69. Cursor Adapter
  • 71. Avoid
  • 72. Use Other Apps private static final int SELECT_VIDEO = 1; private Uri videoUri; @Override protected void onCreate(Bundle savedInstanceState) { Button vidBtn = (Button) findViewById(R.id.vidBtn); vidBtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View button) { Intent videoChooser = new Intent(Intent.ACTION_GET_CONTENT); videoChooser.setType("video/*"); startActivityForResult(videoChooser, SELECT_VIDEO); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == SELECT_VIDEO && resultCode == RESULT_OK){ videoUri = data.getData(); } }
  • 73.
  • 75. Dissolve Animation private void nextSlide() { AlphaAnimation animation = new AlphaAnimation(0.0f, 1.0f); if ((count % 2) == 0) { animation = new AlphaAnimation(1.0f, 0.0f); } animation.setStartOffset(TIME_PER_SLIDE); animation.setDuration(TIME_PER_SLIDE); animation.setFillAfter(true); animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) {} @Override public void onAnimationRepeat(Animation animation) {} @Override public void onAnimationEnd(Animation animation) { if (playingSlides){ nextImage = getNextImage(); ImageView backgroundImage = (count % 2 == 0) ? rightSlide : leftSlide; backgroundImage.setImageBitmap(nextImage); count++; nextSlide(); } } }); rightSlide.startAnimation(animation); currentImage = nextImage; }
  • 77. Animators ImageView backgroundImage = (count % 2 == 0) ? rightSlide : leftSlide; ObjectAnimator anim = ObjectAnimator.ofFloat(backgroundImage, "alpha", 0.0f, 1.0f); anim.addListener(new AnimatorListenerAdapter(){ public void onAnimationEnd(Animator animator){ nextSlide(); } });
  • 78.
  • 79.
  • 81. playBtn.setOnClickListener(new OnClickListener(){ private Handler handler = new Handler(); MediaPlayer player = null; long maxTime = 15L*1000; // 15 seconds long timeLeft = maxTime; Audio Preview Runnable autoStop; @Override public void onClick(View view) { if (player == null){ player = MediaPlayer.create(activity, song.uri); } if (!playingSongs.contains(song.id)){ Start/Resume player.start(); playingSongs.add(song.id); autoStop = new Runnable(){ Timer @Override public void run() { player.pause(); player.seekTo(0); playingSongs.remove(song.id); playBtn.setText(R.string.play); timeLeft = maxTime; } }; handler.postDelayed(autoStop, timeLeft); playBtn.setText(R.string.pause); } else { player.pause(); Pause playingSongs.remove(song.id); timeLeft = maxTime - player.getCurrentPosition(); playBtn.setText(R.string.play); Calc time left handler.removeCallbacks(autoStop); } } });
  • 83. Handler? Pipeline Thread Looper.prepare(); handler = new Handler(); // handle tasks in queue Looper.loop();
  • 84. Handler? Thread Pipeline Thread Looper.prepare(); handler = new Handler(); // handle tasks in queue Looper.loop(); // long running task Message msg = handler.obtainMessage(); handler.sendMessage(msg);
  • 85. Handler? Thread Pipeline Thread Thread Looper.prepare(); handler = new Handler(); // handle tasks in queue // long running task handler.post( Looper.loop(); new Runnable() {... }); // long running task Message msg = handler.obtainMessage(); handler.sendMessage(msg);
  • 86. Theme Muzak private MediaPlayer player; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setupThemeMusic(); } @Override public void onResume() { super.onResume(); if (player != null){ player.start(); } @Override } public void onPause(){ super.onPause(); if (player != null && player.isPlaying()){ player.pause(); } } @Override protected void onDestroy() { super.onDestroy(); if (player != null && player.isPlaying()){ player.stop(); } player.release(); }
  • 88.
  • 89. Video Playback Uri videoUri = ...; VideoView video = (VideoView) findViewById(R.id.video); video.setVideoURI(videoUri); MediaController controller = new MediaController(this); controller.setMediaPlayer(video); video.setMediaController(controller); video.requestFocus(); video.start();
  • 90.
  • 92. Use the Camera (app) import static android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI; Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); photoUri = getContentResolver().insert( EXTERNAL_CONTENT_URI, new ContentValues()); intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(intent,TAKE_PHOTO); @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK && requestCode == TAKE_PHOTO){ ImageView img = (ImageView) findViewById(R.id.photoThumb); InputStream stream = getContentResolver().openInputStream(photoUri); Bitmap bmp = BitmapFactory.decodeStream(stream); img.setImageBitmap(bmp); } }
  • 93.
  • 94. EXIF!
  • 96. Correctly Oriented Options photoImageOptions = new BitmapFactory.Options(); Matrix matrix = new Matrix(); ExifInterface ei = new ExifInterface(somePath); int orientation = ei.getAttributeInt(TAG_ORIENTATION, ORIENTATION_UNDEFINED); int angle = 0; switch (orientation) { case ORIENTATION_ROTATE_90 : angle=90; break; case ORIENTATION_ROTATE_180 : angle=180; break; case ORIENTATION_ROTATE_270 : angle=270; break; default: break; } Bitmap bm = BitmapFactory.decodeFile(path, photoImageOptions); if (angle > 0){ matrix.setRotate(angle); Bitmap bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true); }
  • 97. Geo Tagging ExifInterface exif = new ExifInterface(filename); exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, latitude); exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, longitude); exif.saveAttributes(); “dd/1,mm/1,ss/1”
  • 99. Getting a (geo) fix LocationManager mgr = getSystemService(LOCATION_SERVICE); for (String provider : mgr.getAllProviders()){ Location last = mgr.getLastKnownLocation(last); mgr.requestLocationUpdates(provider, 60000, 500, new LocationListener(){ public void onLocationChanged(Location loc){ // do stuff } // other methods }); }
  • 101. Uploading a photo String url = "http://my/server"; HttpClient client = new DefaultHttpClient(); HttpContext context = new BasicHttpContext(); HttpPost post = new HttpPost(url); File imgFile = new File("/path/to/my/image"); MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); entity.addPart("image", new FileBody(imgFile)); post.setEntity(entity); HttpResponse response = client.execute(httpPost, localContext);
  • 102.
  • 103. Upload Service UploadService extends IntentService { protected void onHandleIntent(Intent i){ String imgPath = i.getStringExtra("file"); // upload code goes here } } Intent i = new Intent(this, UploadService.class); i.putExtra("file", "/path/to/my/image"); startService(i);
  • 104.
  • 105. Process Priority Foreground Visible Service Background Empty
  • 107.
  • 108. Video Preview private SurfaceHolder holder; private Camera camera; private MediaRecorder mediaRecorder; private File tempFile; private SurfaceView preview; private boolean isRecording = false; private final int maxDurationInMs = 20000; private final long maxFileSizeInBytes = 500000; private final int videoFramesPerSecond = 20; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); preview = new SurfaceView(this); holder = preview.getHolder(); holder.addCallback(cameraman); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); setContentView(preview); tempFile = new File(getCacheDir(), "temp.mov"); if (tempFile.length() > 0){ tempFile.delete(); } }
  • 109. Video Preview private Callback cameraman = new Callback(){ @Override public void surfaceCreated(SurfaceHolder holder) { camera = Camera.open(); camera.setPreviewDisplay(holder); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) { Parameters params = camera.getParameters(); List<Size> sizes = params.getSupportedPreviewSizes(); Size optimalSize = getOptimalPreviewSize(sizes, width, height); params.setPreviewSize(optimalSize.width, optimalSize.height); camera.setParameters(params); camera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { camera.stopPreview(); camera.release(); } };
  • 110. Video Preview private void startRecording(){ if (isRecording){ return; } isRecording = true; camera.unlock(); mediaRecorder = new MediaRecorder(); mediaRecorder.setCamera(camera); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); mediaRecorder.setMaxDuration(maxDurationInMs); mediaRecorder.setOutputFile(tempFile.getPath()); mediaRecorder.setVideoFrameRate(videoFramesPerSecond); mediaRecorder.setVideoSize(preview.getWidth(), preview.getHeight()); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT); mediaRecorder.setPreviewDisplay(holder.getSurface()); mediaRecorder.setMaxFileSize(maxFileSizeInBytes); mediaRecorder.prepare(); mediaRecorder.start(); }

Hinweis der Redaktion

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n