I am new to Android development. I created my first app which is a camera with the ability to capture an image, query the user for a Car ID related to the image, preview the captured image, and upload that image to the server.
I am interested in randomly sending out one image from possibly multiple such as from the image directory to the server. I do NOT want to send multiple images to the server--just one random image.
Upon much research on this website as well as on numerous others, I determined the following: I must obtain the image directory to where the captured images are uploaded to, I must randomly select an image from said directory using the random capability in Android, I must set up the image bitmap based on the file uri of the image, and I must convert the bitmap to a blob data type by base64 encoding.
I did the above, but my bitmap returned as null since I receive the message, "Please select image", which was the toast message for that instance.
Here is my code:
public class MainActivity extends Activity {
// Activity request codes.
private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
public static final int MEDIA_TYPE_IMAGE = 1;
Bitmap bitmap;
ProgressDialog pd;
InputStream is;
//Directory name to store captured images.
private static final String IMAGE_DIRECTORY_NAME = "Hello Camera";
private Uri fileUri; //File url to store captured images.
private ImageView imgPreview;
private Button btnCapturePicture;
private Button upload;
Button mButton;
EditText mEdit;
/* Initializes activity, defines UI layout, and retrieves widgets
* to interact with.
* #param savedInstanceState - data is caught here and saved for
* future app use.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button)findViewById(R.id.button);
mEdit = (EditText)findViewById(R.id.edittext);
mButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Log.v("EditText", mEdit.getText().toString());
}
});
imgPreview = (ImageView) findViewById(R.id.imgPreview);
btnCapturePicture = (Button) findViewById(R.id.btnCapturePicture);
upload = (Button) findViewById(R.id.upload);
upload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (bitmap == null) {
Toast.makeText(getApplicationContext(), "Please Select Image", Toast.LENGTH_LONG).show();
} else {
new ImageUpload().execute();
}
}
});
/**
* Captures image button click event in order to capture a photo.
* #param new View.OnClickListener- call to constructor
*/
btnCapturePicture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Captures an image.
captureImage();
}
});
//Checks for camera availability.
if (!isDeviceSupportCamera()) {
Toast.makeText(getApplicationContext(),
"Sorry! Your device doesn't support camera", Toast.LENGTH_LONG).show();
//Closes if a camera is not available on the device.
finish();
}
}
/**
* Checks if device has camera hardware.
*
* #return - true or false.
*/
private boolean isDeviceSupportCamera() {
if (getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
//Device has a camera.
return true;
} else {
// Device does not have a camera.
return false;
}
}
/*
* Launches camera app request image capture.
*/
private void captureImage() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
//Starts the image capture Intent.
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
}
/**
* Gets and stores the file url. Will be null after returning from camera
* app.
*
* #param outState - Holds per-instance state from activity.
*/
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Saves the file url in bundle. It will be null on screen orientation changes.
outState.putParcelable("file_uri", fileUri);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//Gets the file url.
fileUri = savedInstanceState.getParcelable("file_uri");
}
/**
* Receives activity result method. Will be called after closing the camera.
*
* #param requestCode - Requests to capture an image.
* #param resultCode - Based on success or failure of image capturing, shows
* an image preview or one of two error messages.
* #param data - Carries the result data(successfully captured image).
* #return - An image preview, or one of two error messages.
*/
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//If the result is the image capturing event,
if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
//the image was successfully captured
// and will be displayed in the preview.
previewCapturedImage();
} else if (resultCode == RESULT_CANCELED) {
//The user cancelled the image capturing.
Toast.makeText(getApplicationContext(),
"User cancelled image capture", Toast.LENGTH_SHORT).show();
} else {
//Image capturing failed, but the user did not actually cancel it.
Toast.makeText(getApplicationContext(),
"Sorry! Failed to capture image", Toast.LENGTH_SHORT).show();
}
}
}
/**
* Displays the image from a path to ImageView.
* Downsizes an image if necessary and throws exception
* if the image is too large.
*/
private void previewCapturedImage() {
try {
imgPreview.setVisibility(View.VISIBLE);
upload.setVisibility(View.VISIBLE);
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
IMAGE_DIRECTORY_NAME);
Log.v("Directory", mediaStorageDir.toString());
mediaStorageDir.listFiles(new FileFilter() {
public boolean accept(File file) {
return !file.isDirectory();
}
});
File[] listFiles = mediaStorageDir.listFiles();
Log.v("File listFiles", listFiles.toString());
Random r = new Random ();
Log.v("Random r", r.toString());
File randomPicture = listFiles[r.nextInt(listFiles.length)];
Log.v("Random Picture File", randomPicture.toString());
Uri pictureUri = Uri.fromFile(randomPicture);
Log.v("PictureUri", pictureUri.toString());
BitmapFactory.Options options = new BitmapFactory.Options();
// Downsizes images. Will throw OutOfMemory Exception for larger images.
options.inSampleSize = 8;
Bitmap bitmap = BitmapFactory.decodeFile(pictureUri.getPath(), options);
Log.v("Bitmap", bitmap.toString());
ImageView imgView = (ImageView) findViewById(R.id.imgPreview);
Log.v("ImgView", imgView.toString());
imgView.setImageBitmap(bitmap);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
/**
* Creates the file uri to store an image.
*
* #param type - Refers to the captured image.
* #return Uri.fromFile - The file uri to store an image.
*/
public Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
/**
* Returns the captured image.
*
* #param type - Refers to the captured image.
* #return null or mediaFile - mediaFile: Captured
* image inside of timestamped file.
*/
private static File getOutputMediaFile(int type) {
// External sdcard location.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
IMAGE_DIRECTORY_NAME);
Log.v("Directory Two", mediaStorageDir.toString());
// Create the storage directory if it does not exists
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create " + IMAGE_DIRECTORY_NAME + " directory");
return null;
}
}
// Creates a media file name corresponding to a timestamp.
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
/*
* Uploads the saved and captured image to the server.
*/
public class ImageUpload extends AsyncTask<String, String,String> {
String postUrl = "";
public void postURL(String url) {
postUrl = url;
}
/**
* Compresses the selected gallery image and encodes
* compressed image to a base64 string.
*
* #param params
*/
#Override
protected String doInBackground(String... params) {
String result = null;
try {
HttpClient client = new DefaultHttpClient();
String postURL = "";
HttpPost post = new HttpPost("http://IP here/files/justine/image_save.php");
ArrayList<NameValuePair> nameValuePair = new ArrayList<NameValuePair>();
String msg = mEdit.getText().toString();
nameValuePair.add(new BasicNameValuePair("carid",msg));
//Converts image file uri to blob base64
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
byte[] byte_arr = stream.toByteArray();
String image_str = new String(Base64.encode(byte_arr, Base64.DEFAULT));
nameValuePair.add(new BasicNameValuePair("carimage", image_str));
UrlEncodedFormEntity ent = new UrlEncodedFormEntity(nameValuePair, HTTP.UTF_8);
post.setEntity(ent);
HttpResponse responsePOST = client.execute(post);
HttpEntity resEntity = responsePOST.getEntity();
result = EntityUtils.toString(resEntity);
if (resEntity != null) {
Log.i("RESPONSE", EntityUtils.toString(resEntity));
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
Toast.makeText(getApplicationContext(),
"Successfully uploaded", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(),
"Sorry! Failed to upload", Toast.LENGTH_SHORT).show();
}
}
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.justin.myapplication" >
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="22" />
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:anyDensity="true">
</supports-screens>
<!-- Accessing camera hardware -->
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.screen.portrait" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="orientation|keyboard|keyboardHidden"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Logcat:
07-15 13:34:52.998 22775-22775/? D/dalvikvm﹕ Late-enabling CheckJNI
07-15 13:34:53.154 22775-22775/com.example.justin.myapplication D/libEGL﹕ loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
07-15 13:34:53.162 22775-22775/com.example.justin.myapplication D/libEGL﹕ loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
07-15 13:34:53.170 22775-22775/com.example.justin.myapplication D/libEGL﹕ loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
07-15 13:34:53.256 22775-22775/com.example.justin.myapplication D/OpenGLRenderer﹕ Enabling debug mode 0
07-15 13:35:08.795 22775-22775/com.example.justin.myapplication V/EditText﹕ 77869548059
07-15 13:35:10.779 22775-22775/com.example.justin.myapplication V/Directory Two﹕ /storage/emulated/0/Pictures/Hello Camera
07-15 13:35:11.490 22775-22775/com.example.justin.myapplication W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
07-15 13:35:18.350 22775-22775/com.example.justin.myapplication V/Directory﹕ /storage/emulated/0/Pictures/Hello Camera
07-15 13:35:18.412 22775-22775/com.example.justin.myapplication V/File listFiles﹕ [Ljava.io.File;#427723e8
07-15 13:35:18.412 22775-22775/com.example.justin.myapplication V/Random r﹕ java.util.Random#4277d730
07-15 13:35:18.412 22775-22775/com.example.justin.myapplication V/Random Picture File﹕ /storage/emulated/0/Pictures/Hello Camera/IMG_20150713_143026.jpg
07-15 13:35:18.412 22775-22775/com.example.justin.myapplication V/PictureUri﹕ file:///storage/emulated/0/Pictures/Hello%20Camera/IMG_20150713_143026.jpg
07-15 13:35:18.443 22775-22775/com.example.justin.myapplication D/dalvikvm﹕ GC_FOR_ALLOC freed 207K, 3% free 8778K/9024K, paused 19ms, total 21ms
07-15 13:35:18.443 22775-22775/com.example.justin.myapplication I/dalvikvm-heap﹕ Grow heap (frag case) to 8.897MB for 314944-byte allocation
07-15 13:35:18.459 22775-22784/com.example.justin.myapplication D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 3% free 9079K/9332K, paused 18ms, total 18ms
07-15 13:35:18.607 22775-22775/com.example.justin.myapplication V/Bitmap﹕ android.graphics.Bitmap#4275f650
07-15 13:35:18.607 22775-22775/com.example.justin.myapplication V/ImgView﹕ android.widget.ImageView{42748e50 V.ED.... ......I. 0,0-0,0 #7f0c0051 app:id/imgPreview}
I am confused as to why the bitmap is returning null. I appreciate any insight as to why as well as any suggestions of how to improve my current code for my interested goal. Thank you greatly.
I think you are missing a reference to your created directory. Haven't tried this myself, but this might work in your previewCapturedImage() method:
File mediaStorageDir = new File(Environment.getExternalStorageDirectory().toString() + IMAGE_DIRECTORY_NAME);
I think you failed to add IMAGE_DIRECTORY_NAME since I believe you are making that a directory.
mediaStorageDir.listFiles()
Returns a list of files, but it can also contain directories. To only retrieve files, use:
mediaStorageDir.listFiles(new FileFilter() {
public boolean accept(File file) {
return !file.isDirectory();
}
});
Related
I build my app with FileProvider and I want to save the image after I take it. But I can't find the image in the gallery.
I found these source codes from the Android Studio tutorial. I don't know what is the problem. I tried use debugger and I think the createFile() is correct. I also have my bitmap works. It can display the image I take but I can't add the image to the gallery.
I have this in my Manifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.temp.test"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"/>
</provider>
And in the file_paths.xml I have
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external" path="Android/data/com.temp.test/files/Pictures" />
</paths>
This is how I write the activity
private String mCurrentPhotoPath;
private ImageView mImageView;
private ImageButton StartCameraBtn;
private File photoFile = null;
//requestCode
private static final int REQUEST_IMAGE_CAPTURE = 1;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo_note);
mImageView = (ImageView) findViewById(R.id.imageView);
StartCameraBtn = (ImageButton) findViewById(R.id.StartCamera);
StartCameraBtn.setOnClickListener(this);
}
public void onClick(View view)
{
clearAllFocus();
switch (view.getId())
{
case R.id.StartCamera:
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null)
{
try
{
photoFile = createFile();
}
catch (IOException e)
{
e.printStackTrace();
}
if(photoFile != null){
Uri photoURI = FileProvider.getUriForFile(this,
"com.temp.test",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
break;
...
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
mImageView.setImageBitmap(null);
switch (requestCode)
{
case REQUEST_IMAGE_CAPTURE:
if (resultCode == RESULT_OK)
{
setPic();
galleryAddPic();
}
break;
}
}
private File createFile() throws IOException
{
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
private void galleryAddPic()
{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
private void setPic()
{
// 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;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
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 bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
mImageView.setImageBitmap(bitmap);
}
Please help! Thank you!
I use debugger to test the galleryaddpic() and the URI has been accessed sucessfully, but I don't know why I can't add it to the gallery. I can't find the image file in the android VM directory either.
This is the debug log:
https://i.stack.imgur.com/JN9uJ.png
I'm using chickendinner as my domian, and keep is the name of my app.
Thank you!
Call this function in onActivityResult. It worked for me!
It is in fragment.In activity you can use "this" instead of "getActivity()".
private void galleryAddPic() {
File f = new File(imageFilePath); //set your picture's path
try {
MediaStore.Images.Media.insertImage(getActivity().getContentResolver(),
f.getAbsolutePath(), f.getName(), null);
getActivity().sendBroadcast(new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(f)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Your code handles
write new photo as a jpg-file to the filesystem
add new photo to media-db via broadcst Intent.ACTION_MEDIA_SCANNER_SCAN_FILE
create a FileProvider that allow other apps to access private //Android/data/com.temp.test/files/Pictures/... files through a content-uri content://com.temp.test/...
I assume that the media-db scanner has no read-permission to your app-s private data directory Android/data/com.temp.test/files/Pictures via a file-uri and therefore cannot add the new photo to media-db.
Whatsapp and other apps store their received/send photo in public readable internal memory (i.e. /sdcard/PICTURES/WhatsApp/ ) where the media scanner can read it via file-uri via Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.
I donot know, if the media scanner can handle content: -uris instead of file uri-s: You can try this:
private void galleryAddPic()
{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
// assume that mCurrentPhotoPath ="Android/data/com.temp.test/files/Pictures/myTestImage.jpg"
// can be accessed from outside as "content://com.temp.test/myTestImage.jpg"
Uri contentUri = Uri.parse("content://com.temp.test/myTestImage.jpg");
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
Please let us know if this works.
If this does not work you can try to manually insert a "content://com.temp.test/..." entry into media database.
using public readable internal memory directories should work without a fileprovider
I have a working Android app that displays user stats. I want to send a small report with plain text format (.txt) to a WiFi Direct printer. I have downloaded the sample demo app from Android. I did the proper modification in order to look for .txt file. But I don't understand why my code is not working. After selecting the file I want to print, nothing happens.
The current configuration for my EPSON printer bellow.
Wi-Fi Direct Mode : On
Communication Mode: AP
Operation Mode: IEEE802.11g/n
Communication Speed: Auto
SSID: DIRECT-D3A36C54
Channel: 7
Security Level: WPA2-PSK(AES)
Link Status: Unknown
This is the DeviceDetailFragment class
public class DeviceDetailFragment extends Fragment implements WifiP2pManager.ConnectionInfoListener {
protected static final int CHOOSE_FILE_RESULT_CODE = 20;
private View mContentView = null;
private WifiP2pDevice device;
private WifiP2pInfo info;
ProgressDialog progressDialog = null;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mContentView = inflater.inflate(R.layout.device_detail, null);
mContentView.findViewById(R.id.btn_connect).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
config.wps.setup = WpsInfo.LABEL;
config.wps.pin = "12345677";
// config.groupOwnerIntent = 15;
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
progressDialog = ProgressDialog.show(getActivity(), "Press back to cancel",
"Connecting to :" + device.deviceAddress, true, true
// new DialogInterface.OnCancelListener() {
//
// #Override
// public void onCancel(DialogInterface dialog) {
// ((DeviceActionListener) getActivity()).cancelDisconnect();
// }
// }
);
((DeviceListFragment.DeviceActionListener) getActivity()).connect(config);
}
});
mContentView.findViewById(R.id.btn_disconnect).setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
((DeviceListFragment.DeviceActionListener) getActivity()).disconnect();
}
});
mContentView.findViewById(R.id.btn_start_client).setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
// Allow user to pick a text file from storage or other
// registered apps
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("text/*");
// intent.setType("image/*");
startActivityForResult(intent, CHOOSE_FILE_RESULT_CODE);
}
});
return mContentView;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// User has picked a text file. Transfer it to group owner i.e peer using
// FileTransferService.
Uri uri = data.getData();
TextView statusText = (TextView) mContentView.findViewById(R.id.status_text);
statusText.setText("Sending: " + uri);
Log.d(WiFiDirectActivity.TAG, "Intent----------- " + uri);
Intent serviceIntent = new Intent(getActivity(), FileTransferService.class);
serviceIntent.setAction(FileTransferService.ACTION_SEND_FILE);
serviceIntent.putExtra(FileTransferService.EXTRAS_FILE_PATH, uri.toString());
serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_ADDRESS,
info.groupOwnerAddress.getHostAddress());
serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_PORT, 8315); //631
getActivity().startService(serviceIntent);
}
#Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
this.info = info;
this.getView().setVisibility(View.VISIBLE);
// The owner IP is now known.
TextView view = (TextView) mContentView.findViewById(R.id.group_owner);
view.setText(getResources().getString(R.string.group_owner_text)
+ ((info.isGroupOwner == true) ? getResources().getString(R.string.yes)
: getResources().getString(R.string.no)));
// InetAddress from WifiP2pInfo struct.
view = (TextView) mContentView.findViewById(R.id.device_info);
view.setText("Group Owner IP - " + info.groupOwnerAddress.getHostAddress());
// After the group negotiation, we assign the group owner as the file
// server. The file server is single threaded, single connection server
// socket.
if (info.groupFormed && info.isGroupOwner) {
new FileServerAsyncTask(getActivity(), mContentView.findViewById(R.id.status_text))
.execute();
} else if (info.groupFormed) {
// The other device acts as the client. In this case, we enable the
// get file button.
mContentView.findViewById(R.id.btn_start_client).setVisibility(View.VISIBLE);
((TextView) mContentView.findViewById(R.id.status_text)).setText(getResources()
.getString(R.string.client_text));
}
// hide the connect button
mContentView.findViewById(R.id.btn_connect).setVisibility(View.GONE);
}
/**
* Updates the UI with device data
*
* #param device the device to be displayed
*/
public void showDetails(WifiP2pDevice device) {
this.device = device;
this.getView().setVisibility(View.VISIBLE);
TextView view = (TextView) mContentView.findViewById(R.id.device_address);
view.setText(device.deviceAddress);
view = (TextView) mContentView.findViewById(R.id.device_info);
view.setText(device.toString());
}
/**
* Clears the UI fields after a disconnect or direct mode disable operation.
*/
public void resetViews() {
mContentView.findViewById(R.id.btn_connect).setVisibility(View.VISIBLE);
TextView view = (TextView) mContentView.findViewById(R.id.device_address);
view.setText(R.string.empty);
view = (TextView) mContentView.findViewById(R.id.device_info);
view.setText(R.string.empty);
view = (TextView) mContentView.findViewById(R.id.group_owner);
view.setText(R.string.empty);
view = (TextView) mContentView.findViewById(R.id.status_text);
view.setText(R.string.empty);
mContentView.findViewById(R.id.btn_start_client).setVisibility(View.GONE);
this.getView().setVisibility(View.GONE);
}
/**
* A simple server socket that accepts connection and writes some data on
* the stream.
*/
public static class FileServerAsyncTask extends AsyncTask<Void, Void, String> {
private Context context;
private TextView statusText;
/**
* #param context
* #param statusText
*/
public FileServerAsyncTask(Context context, View statusText) {
this.context = context;
this.statusText = (TextView) statusText;
}
#Override
protected String doInBackground(Void... params) {
try {
ServerSocket serverSocket = new ServerSocket(8315); //631
Log.d(WiFiDirectActivity.TAG, "Server: Socket opened");
Socket client = serverSocket.accept();
Log.d(WiFiDirectActivity.TAG, "Server: connection done");
// final File f = new File(Environment.getExternalStorageDirectory() + "/"
// + context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
// + ".txt");
final File f = new File(Environment.getExternalStorageDirectory() + "/"
+ context.getPackageName() + "/wifip2pshared-" + ".txt");
File dirs = new File(f.getParent());
if (!dirs.exists())
dirs.mkdirs();
f.createNewFile();
Log.d(WiFiDirectActivity.TAG, "server: copying files " + f.toString());
InputStream inputstream = client.getInputStream();
copyFile(inputstream, new FileOutputStream(f));
serverSocket.close();
return f.getAbsolutePath();
} catch (IOException e) {
Log.e(WiFiDirectActivity.TAG, e.getMessage());
return null;
}
}
/*
* (non-Javadoc)
* #see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
#Override
protected void onPostExecute(String result) {
if (result != null) {
statusText.setText("File copied - " + result);
// Log.e("...File copied - ", result);
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + result), "text/*");
context.startActivity(intent);
} else {
Log.e("File copied is NULL- ", result);
}
}
/*
* (non-Javadoc)
* #see android.os.AsyncTask#onPreExecute()
*/
#Override
protected void onPreExecute() {
statusText.setText("Opening a server socket");
}
}
public static boolean copyFile(InputStream inputStream, OutputStream out) {
byte buf[] = new byte[1024];
int len;
try {
while ((len = inputStream.read(buf)) != -1) {
out.write(buf, 0, len);
}
out.close();
inputStream.close();
} catch (IOException e) {
Log.d(WiFiDirectActivity.TAG, e.toString());
return false;
}
return true;
}
}
EDIT #1
This is my permission setting
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BIND_PRINT_SERVICE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
After connecting to the printer, I've got the UI to select the file, after I select it, nothing happens, I just got the below console output (the file I am picking up is located in the SD card)
05-17 10:39:50.994 28659-28659/com.example.ccano.wifidirect E/ViewRootImpl: sendUserActionEvent() mView == null
05-17 10:39:52.314 28659-28659/com.example.ccano.wifidirect D/ViewRootImpl: ViewPostImeInputStage processPointer 0
05-17 10:39:52.384 28659-28659/com.example.ccano.wifidirect D/ViewRootImpl: ViewPostImeInputStage processPointer 1
05-17 10:39:56.484 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: Intent-----------
content://com.android.externalstorage.documents/document/9C33-6BBD%3Asample_file.txt
05-17 10:39:56.514 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: P2P state changed - 2
05-17 10:39:56.514 28659-29309/com.example.ccano.wifidirect D/wifidirectdemo: Opening client socket -
05-17 10:39:56.514 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: Peer status :0
05-17 10:39:56.524 28659-29309/com.example.ccano.wifidirect D/wifidirectdemo: Client socket - true
05-17 10:39:56.524 28659-29309/com.example.ccano.wifidirect E/ccano..copyfile: true
05-17 10:39:56.524 28659-29309/com.example.ccano.wifidirect D/wifidirectdemo: Client: Data written
05-17 10:39:56.534 28659-28659/com.example.ccano.wifidirect I/Timeline: Timeline: Activity_idle id:
android.os.BinderProxy#75dd5e time:4602644
05-17 10:41:01.714 28659-28659/com.example.ccano.wifidirect D/ViewRootImpl: ViewPostImeInputStage processPointer 0
05-17 10:41:01.774 28659-28659/com.example.ccano.wifidirect D/ViewRootImpl: ViewPostImeInputStage processPointer 1
05-17 10:41:02.564 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: P2P peers changed
05-17 10:41:02.574 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: Peer status :3
05-17 10:41:02.594 28659-28659/com.example.ccano.wifidirect D/wifidirectdemo: No devices found
EDIT #2
After adding the below line into my manifiest, still I am getting same result, nothing happens.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Edit #3
After changing WpsInfo.Label to WpsInfo.PBC now, I am getting a different output on the debugger console. (see screen shot below). But, still I the printer is not sending the print job.
It turned out that my code was fine, after several days of testing and doing research, I found out that the issue was the socket class, I was using the default one that Google provides in the demo code (which is the one I was using) but, after reading the official documentation from Wi-Fi.org I could understand that port number matters and, in order to make it work with WiFi Direct only you have to target port #631 and the printer will ask you about the PIN password in case that it is enabled. Now, if you want to use P2P and by-passing the password, you have to use the port #9100.
So, I did it using both ports 9100 and 631 and now I am printing txt files.
Now, if you want to print PDF, you just need to add:
intent.setType("application/pdf");
and
intent.setDataAndType(Uri.parse("file://" + result), "application/pdf");
to the DeviceDetailFragment class (the one is posted above).
I hope this post will provide a good understanding and inside about Android printing with P2P communication.
I have an Android app that writes .txt files to the downloads folder based off your inputs, a listview that displays all your downloads and lets you click to view them (I have this working), and I'm now trying to code a way to upload them to Google Drive. I have done the developer's verification process with the SHA1 key so it should be fine as far as that goes. I often see this demo app that takes pictures and uploads them being recommended and it looks like a good code to start with and modify, but when I run it on my phone, it doesn't work-it just repeatedly asks me to select my account endlessly. The java code inside the project itself is this (I'm pretty new and don't quite understand how all of it works, but this is for the google demo in the link):
public class MainActivity extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener {
private static final String TAG = "drive-quickstart";
private static final int REQUEST_CODE_CAPTURE_IMAGE = 1;
private static final int REQUEST_CODE_CREATOR = 2;
private static final int REQUEST_CODE_RESOLUTION = 3;
private GoogleApiClient mGoogleApiClient;
private Bitmap mBitmapToSave;
/**
* Create a new file and save it to Drive.
*/
private void saveFileToDrive() {
// Start by creating a new contents, and setting a callback.
Log.i(TAG, "Creating new contents.");
final Bitmap image = mBitmapToSave;
Drive.DriveApi.newDriveContents(mGoogleApiClient)
.setResultCallback(new ResultCallback<DriveContentsResult>() {
#Override
public void onResult(DriveContentsResult result) {
// If the operation was not successful, we cannot do anything
// and must
// fail.
if (!result.getStatus().isSuccess()) {
Log.i(TAG, "Failed to create new contents.");
return;
}
// Otherwise, we can write our data to the new contents.
Log.i(TAG, "New contents created.");
// Get an output stream for the contents.
OutputStream outputStream = result.getDriveContents().getOutputStream();
// Write the bitmap data from it.
ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, bitmapStream);
try {
outputStream.write(bitmapStream.toByteArray());
} catch (IOException e1) {
Log.i(TAG, "Unable to write file contents.");
}
// Create the initial metadata - MIME type and title.
// Note that the user will be able to change the title later.
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
.setMimeType("image/jpeg").setTitle("Android Photo.png").build();
// Create an intent for the file chooser, and start it.
IntentSender intentSender = Drive.DriveApi
.newCreateFileActivityBuilder()
.setInitialMetadata(metadataChangeSet)
.setInitialDriveContents(result.getDriveContents())
.build(mGoogleApiClient);
try {
startIntentSenderForResult(
intentSender, REQUEST_CODE_CREATOR, null, 0, 0, 0);
} catch (SendIntentException e) {
Log.i(TAG, "Failed to launch file chooser.");
}
}
});
}
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
// Create the API client and bind it to an instance variable.
// We use this instance as the callback for connection and connection
// failures.
// Since no account name is passed, the user is prompted to choose.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
// Connect the client. Once connected, the camera is launched.
mGoogleApiClient.connect();
}
#Override
protected void onPause() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onPause();
}
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_CODE_CAPTURE_IMAGE:
// Called after a photo has been taken.
if (resultCode == Activity.RESULT_OK) {
// Store the image data as a bitmap for writing later.
mBitmapToSave = (Bitmap) data.getExtras().get("data");
}
break;
case REQUEST_CODE_CREATOR:
// Called after a file is saved to Drive.
if (resultCode == RESULT_OK) {
Log.i(TAG, "Image successfully saved.");
mBitmapToSave = null;
// Just start the camera again for another photo.
startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
REQUEST_CODE_CAPTURE_IMAGE);
}
break;
}
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Called whenever the API client fails to connect.
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// show the localized error dialog.
GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization
// dialog is displayed to the user.
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "API client connected.");
if (mBitmapToSave == null) {
// This activity has no UI of its own. Just start the camera.
startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
REQUEST_CODE_CAPTURE_IMAGE);
return;
}
saveFileToDrive();
}
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
}
}
And in the manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.gms.drive.sample.quickstart"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.google.android.gms.drive.sample.quickstart.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
</manifest>
And with that, my main two questions are:
Any idea why the quick start project from Google is behaving the way it is?
If it's not too much, but what parts of the java code do I need to modify to make it upload a .txt file after pressing a button?
You are supposed to create a project in Google Api COnsole,then enable Drive API. Then create required credentials(SHA-1, key, CLIENT-ID) for the the android app to connect with drive api.
After getting all the credentials, include them in Manifest file and String File.
Follow the instructions here, QuickStart Android Instructions
I want to make an app that takes a picture with the device's camera, saves the image in the internal memory, and then displays that image in the next Activity. The preview works perfectly, but when I hit the Capture button the app goes to the next activity and only shows a blank white screen. Maybe I'm not writing or reading the file correctly?
Here is the Main Activity:
public class MainActivity extends ActionBarActivity {
public final static String EXTRA_MESSAGE = "File_name";
private Camera mCamera;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create an instance of Camera
mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
CameraPreview mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
}
//////////////////////
public void sendInfo(String pathway) {
Intent intent = new Intent(this, show_image.class);
intent.putExtra(EXTRA_MESSAGE,pathway);
startActivity(intent);
}
/////////////////
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data , Camera camera) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
File mypath=new File(directory,"pic.jpg");
FileOutputStream fos = null;
if (directory == null){
Log.d("Logtag", "Error creating media file, check storage permissions: ");
return;
}
try {
fos = new FileOutputStream(mypath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
String path = directory.getAbsolutePath();
sendInfo(path);
} catch (FileNotFoundException e) {
Log.d("Logtag", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("Logtag", "Error accessing file: " + e.getMessage());
}
}
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A safe way to get an instance of the Camera object.
*/
public Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
} catch (Exception e) {
// Camera is not available (in use or does not exist)
Toast.makeText(getApplicationContext(), "Camera is not available (in use or does not exist)",
Toast.LENGTH_LONG).show();
}
return c; // returns null if camera is unavailable
}
}
Here is the Second activity that is supposed to display the image that was just taken:
public class show_image extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
String path = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
try {
File f = new File(path, "pic.jpg");
Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
ImageView img= new ImageView(this);
img.setImageBitmap(b);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
public static Bitmap decodeFile(File f, final int maxSize) {
Bitmap b = null;
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
BitmapFactory.decodeStream(fis, null, o);
fis.close();
int scale = 1;
if (o.outHeight > maxSize || o.outWidth > maxSize) {
scale = (int) Math.pow(2, (int) Math.round(Math.log(maxSize / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
fis = new FileInputStream(f);
b = BitmapFactory.decodeStream(fis, null, o2);
} catch (Exception e) {
Log.e("Logtag", "Error processing bitmap", e);
} finally {
//FileUtil.closeQuietly(fis);
}
return b;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
The LogCat from Android Studio:
02-25 12:32:49.389 17041-17041/edu.ramapo.camer I/System.out﹕ debugger has settled (1496)
02-25 12:32:49.620 17041-17041/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.view.ViewGroup.onNestedScrollAccepted, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.onNestedScrollAccepted
02-25 12:32:49.620 17041-17041/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 11360: Landroid/view/ViewGroup;.onNestedScrollAccepted (Landroid/view/View;Landroid/view/View;I)V
02-25 12:32:49.620 17041-17041/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6f at 0x0000
02-25 12:32:49.620 17041-17041/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.view.ViewGroup.onStopNestedScroll, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.onStopNestedScroll
02-25 12:32:49.620 17041-17041/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 11366: Landroid/view/ViewGroup;.onStopNestedScroll (Landroid/view/View;)V
02-25 12:32:49.620 17041-17041/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6f at 0x0000
02-25 12:32:49.630 17041-17041/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.support.v7.internal.widget.ActionBarOverlayLayout.stopNestedScroll, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.setHideOnContentScrollEnabled
02-25 12:32:49.630 17041-17041/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 9050: Landroid/support/v7/internal/widget/ActionBarOverlayLayout;.stopNestedScroll ()V
02-25 12:32:49.630 17041-17041/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x000e
02-25 12:32:49.660 17041-17041/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method
android.support.v7.internal.widget.TintTypedArray.getChangingConfigurations
02-25 12:32:49.660 17041-17041/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 367: Landroid/content/res/TypedArray;.getChangingConfigurations ()I
02-25 12:32:49.660 17041-17041/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002
02-25 12:32:49.670 17041-17041/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.internal.widget.TintTypedArray.getType
02-25 12:32:49.670 17041-17041/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 389: Landroid/content/res/TypedArray;.getType (I)I
02-25 12:32:49.670 17041-17041/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002
02-25 12:32:50.611 17041-17041/edu.ramapo.camer D/libEGL﹕ loaded /system/lib/egl/libEGL_adreno200.so
02-25 12:32:50.621 17041-17041/edu.ramapo.camer D/libEGL﹕ loaded /system/lib/egl/libGLESv1_CM_adreno200.so
02-25 12:32:50.621 17041-17041/edu.ramapo.camer D/libEGL﹕ loaded /system/lib/egl/libGLESv2_adreno200.so
02-25 12:32:50.631 17041-17041/edu.ramapo.camer I/Adreno200-EGL﹕ <qeglDrvAPI_eglInitialize:265>: EGL 1.4 QUALCOMM build: HAREESHG_Nondeterministic_AU+PATCH[ES]_msm8960_JB_1.9.6_MR2_CL3219408_release_ENGG (CL3219408)
Build Date: 09/28/13 Sat
Local Branch: hhh
Remote Branch: quic/jb_1.9.6_1
Local Patches: 8d50ec23e42ef52b570aa6ff1650afac0b503d78 CL3219408: Fix in the Glreadpixels for negative offsets and larger dimensions.
801859126f6ca69482b39a34ca61447e3f7cded8 rb: fix panel settings to clear undrawn/undefined buffers
Reconstruct Branch: LOCAL_PATCH[ES]
02-25 12:32:50.991 17041-17041/edu.ramapo.camer D/OpenGLRenderer﹕ Enabling debug mode 0
02-25 12:32:51.552 17041-17041/edu.ramapo.camer I/Choreographer﹕ Skipped 59 frames! The application may be doing too much work on its main thread.
02-25 12:32:56.037 17041-17047/edu.ramapo.camer D/dalvikvm﹕ Debugger has detached; object registry had 4113 entries
02-25 12:33:18.651 17041-17041/edu.ramapo.camer D/dalvikvm﹕ GC_FOR_ALLOC freed 694K, 38% free 12155K/19420K, paused 29ms, total 32ms
02-25 12:33:18.771 17041-17041/edu.ramapo.camer I/dalvikvm-heap﹕ Grow heap (frag case) to 45.705MB for 31961104-byte allocation
02-25 12:33:24.507 17041-17041/edu.ramapo.camer D/dalvikvm﹕ GC_FOR_ALLOC freed 31627K, 40% free 11825K/19424K, paused 30ms, total 30ms
02-25 12:33:24.587 17041-17041/edu.ramapo.camer I/dalvikvm-heap﹕ Grow heap (frag case) to 45.382MB for 31961104-byte allocation
Well right now I made a copy of the app I sent you the link already here is the code:
public class GlassARTest extends FragmentActivity {
private static final String TAG = "CameraActivity";
public static final int MEDIA_TYPE_IMAGE = 1;
private Camera mCamera;
private CameraPreview mPreview;
private Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
mContext = this;
if(checkCameraHardware(mContext)){
// Create an instance of Camera
mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
}
}
private PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: ");
return null;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
return pictureFile.getPath();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
return null;
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
return null;
}
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(result != null){
Intent intent = new Intent(mContext, ImageDisplayActivity.class);
intent.putExtra(ImageDisplayActivity.KEY_PATH, result);
startActivity(intent);
}
}
}.execute();
}
};
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
} private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
}
and the other Activity:
public class ImageDisplayActivity extends FragmentActivity{
public static final String KEY_PATH = "path";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_display);
final ImageView imageDisplay = (ImageView)findViewById(R.id.image_displayer);
final Bundle extras = getIntent().getExtras();
if(extras != null){
final String path = extras.getString(KEY_PATH);
File imgFile = new File(path);
Bitmap bitmap = decodeFile(imgFile);
imageDisplay.setImageBitmap(bitmap);
}
}
private Bitmap decodeFile(File f){
Bitmap b = null;
try {
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream fis = new FileInputStream(f);
BitmapFactory.decodeStream(fis, null, o);
fis.close();
int scale = 1;
if (o.outHeight > 50 || o.outWidth > 50) {
scale = (int)Math.pow(2, (int) Math.round(Math.log(50 / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
fis = new FileInputStream(f);
b = BitmapFactory.decodeStream(fis, null, o2);
fis.close();
} catch (IOException e) {
}
return b;
}
}
this code worked showing a pixelated image of what I took picture of (as I'm just decoding it in low quality for testing purposes).
I hope this help you.
I have been following this tutorial: AndroidHive - working with Camera API to try and enable taking photos in my app. However, I'm getting an error once I press my "take photo button".
LogCat:
09-16 11:04:00.539 19561-19561/au.gov.nsw.shellharbour.saferroadsshellharbour D/Dob_in_a_Hoon_photos﹕ Failed to create Dob_in_a_Hoon_photos directory
09-16 11:04:00.539 19561-19561/au.gov.nsw.shellharbour.saferroadsshellharbour D/AndroidRuntime﹕ Shutting down VM
09-16 11:04:00.539 19561-19561/au.gov.nsw.shellharbour.saferroadsshellharbour W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x40e21438)
09-16 11:04:00.559 19561-19561/au.gov.nsw.shellharbour.saferroadsshellharbour E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException: file
at android.net.Uri.fromFile(Uri.java:441)
at au.gov.nsw.shellharbour.saferroadsshellharbour.dob_in_a_hoon.getOutputMediaFileUri(dob_in_a_hoon.java:97)
at au.gov.nsw.shellharbour.saferroadsshellharbour.dob_in_a_hoon.captureImage(dob_in_a_hoon.java:89)
at au.gov.nsw.shellharbour.saferroadsshellharbour.dob_in_a_hoon.access$000(dob_in_a_hoon.java:28)
at au.gov.nsw.shellharbour.saferroadsshellharbour.dob_in_a_hoon$1.onClick(dob_in_a_hoon.java:60)
at android.view.View.performClick(View.java:4191)
at android.view.View$PerformClick.run(View.java:17229)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4963)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
09-16 11:04:10.529 19561-19561/au.gov.nsw.shellharbour.saferroadsshellharbour I/Process﹕ Sending signal. PID: 19561 SIG: 9
Here is my .java file:
public class dob_in_a_hoon extends ActionBarActivity {
private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
public static final int MEDIA_TYPE_IMAGE = 1;
private static final String IMAGE_DIRECTORY_NAME = "Dob_in_a_Hoon_photos";
private Uri fileUri;
private ImageView Hoon_Image;
private Button button_take_photo;
private String driver_spinner_array[];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dob_in_a_hoon);
driver_spinner_array = new String[2];
driver_spinner_array[0] = "Yes";
driver_spinner_array[1] = "No";
Spinner Driver_spinner = (Spinner) findViewById(R.id.driver_selector);
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, driver_spinner_array);
Driver_spinner.setAdapter(adapter);
Hoon_Image = (ImageView) findViewById(R.id.CapturedImage);
button_take_photo = (Button)findViewById(R.id.btn_take_photo);
button_take_photo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
captureImage();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.dob_in_a_hoon, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void captureImage(){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
}
public Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
private static File getOutputMediaFile(int type){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),IMAGE_DIRECTORY_NAME);
if (!mediaStorageDir.exists()){
if (!mediaStorageDir.mkdirs()){
Log.d(IMAGE_DIRECTORY_NAME, "Failed to create " + IMAGE_DIRECTORY_NAME + " directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
File mediaFile;
if (type==MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath()+File.separator+"IMG_"+timeStamp+".jpg");
}else {
return null;
}
return mediaFile;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE){
if (resultCode==RESULT_OK){
previewCapturedImage();
}else if (resultCode == RESULT_CANCELED){
Toast.makeText(getApplicationContext(),"User Cancelled image Capture", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(getApplicationContext(),"Failed to capture image", Toast.LENGTH_SHORT).show();
}
}
}
private void previewCapturedImage(){
try{
Hoon_Image.setVisibility(View.VISIBLE);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),options);
Hoon_Image.setImageBitmap(bitmap);
}catch (NullPointerException e){
e.printStackTrace();
}
}
#Override
protected void onSaveInstanceState(Bundle outState){
super .onSaveInstanceState(outState);
outState.putParcelable("file_uri", fileUri);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
fileUri = savedInstanceState.getParcelable("file_uri");
}
}
Can anybody see where I am going wrong in my code, and what I have to do to fix it?
I created a sample snippet and tested out the mkdirs as shown in your code, it causes similar exception if i removed the permissions
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Can you please check your manifest to make sure you have these defined.
If above is not the problem, another (unlikely) source of error could be your SD card is running out of space or some permissions restrictions. In this case, i would try the app on android emulator or another device.
This should be added in Manifest to use camera feature:
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:glEsVersion="0x00020000"
android:required="true"/>