Está en la página 1de 46

Lecture 8

Apps with Multimedia

CENG 435 Mobile Application development Fall 14-15


Basics

you should make sure your manifest has the


appropriate declarations to allow use of
camera hardware and other related features.
Basics 2
A quick way to enable taking pictures or videos in
your application without a lot of extra code is to
use an Intent to invoke an existing Android
camera application.
A camera intent makes a request to capture a
picture or video clip through an existing camera
app and then returns control back to your
application.
This section shows you how to capture an image
or video using this technique.
Basics 3: the steps
PART 1

Taking photos
with the
camera App
Take a photo
This can be done by easily creating the Intent responsible for the
camera and calling startActivityforResult()
static final int REQUEST_IMAGE_CAPTURE = 1;
Look at the
private void dispatchTakePictureIntent() { intent
Intent i= name!
new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (i.resolveActivity(getPackageManager())
!= null)
{
startActivityForResult(i,
REQUEST_IMAGE_CAPTURE); Remember
} this?
}
Why startActivityforResult and not
startActivity
Getting the thumbnail back!
The Android Camera application encodes the
photo in the return Intent delivered to
onActivityResult() as a small Bitmap in
the extras, under the key "data".

The following code retrieves this image and


displays it in some ImageView we have
previously created in our layout, for example
image1.
Getting the thumbnail back!

protected void onActivityResult(int requestCode, int resultCode,


Intent i) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode ==
RESULT_OK) {
Extract the
Bundle extras = i.getExtras();
extras from
the intent
Bitmap imageBitmap = (Bitmap) extras.get("data");
Extract
data from
extras
ImageView image1 = (ImageView) findViewById(R.id.myimage)
image1.setImageBitmap(imageBitmap);
}
} Set bitmap
BUT
The previous code actually handles image
thumbnails and not the actual image.

To save the full size photo, look next.


Saving a photo in file

The Android Camera application saves a full-size


photo if you give it a file to save into.

You must provide a fully qualified file name


where the camera app should save the photo.
You send this file with the intent before calling
startActivityForResult.
Saving a photo in file
Generally, any photos that the user captures with
the device camera should be saved on the device in
the public external storage so they are accessible by
all apps.

The proper directory for shared photos is provided


by
getExternalStoragePublicDirectory(),
with the DIRECTORY_PICTURES argument.
Saving a photo in file
Because the directory provided by this method is
shared among all apps, reading and writing to it
requires the READ_EXTERNAL_STORAGE and
WRITE_EXTERNAL_STORAGE permissions,
respectively.
The write permission implicitly allows reading
(covered before)
steps

1 Create a method that will generate a:


Collision resistant file name
Save the path where the image will be saved.

2 Create the intent, add the file to it from the


previous step

3 Call StartActivityForResult
1 Step 1
String mCurrentPhotoPath; // public variable inside your activity

private File createImageFile() throws IOException { Make sure you import


util.date not sql.date
// Create an image file name
String timeStamp = new
SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir =
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);

// get the absolute path


mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
Naming your image

We are just trying to create a unique name,


we could have used a normal string to name
our image

String imageFileName = "JPEG_" +


timeStamp + "_";
get the directory path where android saves
photos

File storageDir =
Environment.getExternalStoragePu
blicDirectory(
Environment.DIRECTOR
Y_PICTURES);
Create a the file name to be collision free!

File image = File.createTempFile(


imageFileName, /* prefix
*/
".jpg", /* suffix
*/
storageDir /*
directory */
);
Save the full path for later use

mCurrentPhotoPath =
image.getAbsolutePath();
static final int REQUEST_TAKE_PHOTO = 1;
Step 2: create the intent and use the
2
Public void myOnClickMethod(View v) {
previous method
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile(); // we used the method from previous step
} catch (IOException ex) {
// Error occurred while creating the File}

// Continue only if the File was successfully created


if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);}}}

Add the file


to the
intent
decode and scale image to be displayed inside
your app
void onActivityResult(int requestCode, int resultCode, Intent i){
// Get the dimensions of the View
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();

// Get the dimensions of the bitmap


BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;

// Determine how much to scale down the image


int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;

Bitmap b= BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);


mImageView.setImageBitmap(b);}
There are 2 versions of decodefile
Add the photo to the gallery
Your image is saved to the directory but not always Or
ACTION_MEDIA_M
showable in the gallery of the phone. To do this: OUNTED if not
KitKat version
Intent i= new
Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
i.setData(contentUri);
this.sendBroadcast(i);

You can add the above code inside onActivityResult which means after the photo has
been taken and you came back to your app.
ImageView Scale types
ImageView scales

<ImageView
android:layout_width="300dp"
android:layout_height="300dp"
android:id="@+id/imageView"
android:src="@drawable/leopard"
android:layout_below="@+id/textView"
android:layout_centerHorizontal="true"
android:layout_marginTop="52dp" />
android:scaleTypes=

"centerInside "center "centerCrop FitXY


We can also set the size of the imageView
programmatically

// Example that sets the image size to 80 x 80

ViewGroup.LayoutParams lp= myImageView.getLayoutParams();

lp.width = 80;

lp.height = 80;

myImageView.setLayoutParams(lp);
One buggy thing!!
When the camera opens, sometimes it
rotates, which might reload your activity.
You know when orientation changes, oncreate
is called again.
To prevent this and prevent crashing, add this
to your <Activity> tag in the manifest file to
tell Android to IGNORE orientation changes.
The screen still orientates, but android wont
take any action.
android:configChanges="orientation|keyboardHidden|screenSize"
SurfaceView

If you dont want to call another camera app


to take your pics, you can actually open the
camera form within YOUR app

To do this, you have to use SurfaceView


inside your xml

Check the details online.


ListView with photos

Same example of the dish but now we can


take a photo of the dish.
If we dont choose a photo, then a default
photo is shown.

Many codes wont be shown here, check


original files.
Opens
camera
The database

public static final String column_id = "_id";


public static final String column_dishname = "dishname";
public static final String column_nofingredients = "nofingredients";
public static final String column_type = "dishtype";
public static final String column_price = "price";
public static final String column_photopath = "photopath";
Add dish function

public void adddish(String dname, int nofingred, String dtype, int p, String photopath )
{

SQLiteDatabase db = this.getWritableDatabase();

ContentValues cv = new ContentValues();

cv.put(column_dishname,dname);
cv.put(column_nofingredients,nofingred);
cv.put(column_price,p);
cv.put(column_type, dtype);
cv.put(column_photopath,photopath);

db.insert(table_name, null, cv);


db.close(); }
Get all dishes

public Cursor getAllDishes(){

Cursor c;
String sqlQuery = "SELECT * FROM " + table_name;
SQLiteDatabase db = this.getReadableDatabase();
c = db.rawQuery(sqlQuery,null);
return c;

}
XMLs

List_item.xml

Linear layout (horizontal) containing an imageView and another Linear Layout (vertical)
that contains the textviews
Custom adapter
public class CustomAdapter extends CursorAdapter {

Dbhelper helper;
Context my_context; // will be used later for getResources functions.
public CustomAdapter(Context con, Cursor cur){

super (con, cur, 0);


my_context= con;
helper = new Dbhelper(con);
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {

return LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);


}
Custom adapter continued
@Override
public void bindView(View view, Context context, Cursor cursor) {

// grab them from the layout, specifically from the "view" argument.

TextView dname = (TextView) view.findViewById(R.id.item_name);


TextView dtype = (TextView) view.findViewById(R.id.item_type);
TextView nofingred = (TextView) view.findViewById(R.id.item_nofingredients);
TextView price = (TextView) view.findViewById(R.id.item_price);
ImageView iv = (ImageView) view.findViewById(R.id.item_image);

// grab the values from the cursor. the cursor is the result of some database query.
String n = cursor.getString(cursor.getColumnIndexOrThrow(helper.column_dishname));
String t = cursor.getString(cursor.getColumnIndexOrThrow(helper.column_type));
int i = cursor.getInt(cursor.getColumnIndexOrThrow(helper.column_nofingredients));
int p = cursor.getInt(cursor.getColumnIndexOrThrow(helper.column_price));
int rowid = cursor.getInt(cursor.getColumnIndexOrThrow(helper.column_id));
String path = cursor.getString(cursor.getColumnIndexOrThrow(helper.column_photopath));
Still inside bindView
dname.setText(n);
dtype.setText(t);
nofingred.setText(String.valueOf(i));
price.setText(String.valueOf(p));

if (path.equals("nophoto")) { // if the user doesnt take a photo, the attribute photopath


will be nophoto
iv.setImageResource(R.drawable.dishpic);
}
else {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
int scaleFactor = Math.min(photoW / 100, photoH / 100);
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
Bitmap b = BitmapFactory.decodeFile(path, bmOptions);

iv.setImageBitmap(b); } }}
Add dish activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_dish_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

path = "nophoto";
dname = (EditText) findViewById(R.id.dishname);
dtype = (EditText) findViewById(R.id.dishtype);
dingredients = (EditText) findViewById(R.id.nofingredients);
dprice = (EditText) findViewById(R.id.price);
db = new Dbhelper(this);
imView = (ImageButton) findViewById(R.id.imageView);
Add dish, still inside oncreate
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String n,t;
int i,p;

n = dname.getText().toString();
t = dtype.getText().toString();
i = Integer.parseInt(dingredients.getText().toString());
p = Integer.parseInt(dprice.getText().toString());

db.adddish(n, i, t, p, path);

Toast.makeText(getApplicationContext(),"Dish saved",Toast.LENGTH_SHORT).show();
dname.setText("");
dingredients.setText("");
dprice.setText("");
dtype.setText("");
imView.setImageResource(R.drawable.dishpic);}});
Bonus
Pick images from your gallery
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Select Picture"),1);

public void onActivityResult(int requestCode, int resultCode, Intent


data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
// do whatever you want with the path from now on.
}
}
}
Cont.
Example with SeekBar
xml
Code
public class MainActivity extends ActionBarActivity {
SeekBar sb;
ImageView i;
ViewGroup.LayoutParams lp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

i = (ImageView) findViewById(R.id.myimageView);
lp = i.getLayoutParams();
sb = (SeekBar) findViewById(R.id.seekBar);

sb.setMax(300);
Code cont.
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
lp.width=100+progress;
lp.height=100+progress;
i.setLayoutParams(lp);
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

}
});}

También podría gustarte