Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialLucian Thomaz da Silva
9,631 PointsChoose pic and video works, Take pic and video crash
Hello guys, Basically the app works fine for choosing an existing picture or video but crashes when I try to take a picture or a video. When debugging the app I found out that the variable mMediaUri was getting a null value if I put a break point on the RecipientsActivity.java only to check its value. But, what is really weird is that if I put a break point right in MainActivity.java, the mMediaUri never gets a null value, it always works. So I can't understand what is happening, is the proccess just so fast that the variable doesn't even get time to be set? Saying that out aloud sounds like a joke haha. I'm testing it on a real device Galaxy s4 by the way. I really apreciate any help.
[Update] I've tested on Genymotion and it works fine, with no problem at all. I have android 5.0 on my Galaxy S4 and I've used Google Nexus 5 with android 4.4.4 on Genymotion. It may be related to my device itself or with the android version perhaps. I'd really like to get it working on my device, but at least I'm feeling better now knowing that it works on the emulator. [Update]
MainActivity.java
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener {
public static final String TAG = MainActivity.class.getSimpleName();
public static final int TAKE_PHOTO_REQUEST = 0;
public static final int TAKE_VIDEO_REQUEST = 1;
public static final int PICK_PHOTO_REQUEST = 2;
public static final int PICK_VIDEO_REQUEST = 3;
public static final int MEDIA_TYPE_IMAGE = 4;
public static final int MEDIA_TYPE_VIDEO = 5;
public static final int FILE_SIZE_LIMIT = 1024*1024*10; // 10 MB
protected Uri mMediaUri;
protected DialogInterface.OnClickListener mDialogListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch(which){
case 0: // Take picture
Intent takePhotoItent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
mMediaUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
if(mMediaUri == null) {
// display an error
Toast.makeText(MainActivity.this, R.string.error_external_storage, Toast.LENGTH_LONG).show();
}
else {
takePhotoItent.putExtra(MediaStore.EXTRA_OUTPUT, mMediaUri);
startActivityForResult(takePhotoItent, TAKE_PHOTO_REQUEST);
}
break;
case 1: // Take video
Intent videoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
mMediaUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);
if(mMediaUri == null) {
// display an error
Toast.makeText(MainActivity.this, R.string.error_external_storage, Toast.LENGTH_LONG).show();
}
else {
videoIntent.putExtra(MediaStore.EXTRA_OUTPUT, mMediaUri);
videoIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 10);
videoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
startActivityForResult(videoIntent, TAKE_VIDEO_REQUEST);
}
break;
case 2: //Choose picture
Intent choosePhotoIntent = new Intent(Intent.ACTION_GET_CONTENT);
choosePhotoIntent.setType("image/*");
startActivityForResult(choosePhotoIntent, PICK_PHOTO_REQUEST);
break;
case 3: // Choose video
Intent chooseVideoIntent = new Intent(Intent.ACTION_GET_CONTENT);
chooseVideoIntent .setType("video/*");
Toast.makeText(MainActivity.this, getString(R.string.video_file_size_warning), Toast.LENGTH_LONG).show();
startActivityForResult(chooseVideoIntent, PICK_VIDEO_REQUEST);
break;
}
}
private Uri getOutputMediaFileUri(int mediaType) {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
if (isExternalStorageAvailable()) {
// get the Uri
//1. Get the external storage directory
String appName = MainActivity.this.getString(R.string.app_name);
File mediaStorageDir = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
appName);
//2. Create our subdirectory
if (! mediaStorageDir.exists()) {
if(! mediaStorageDir.mkdirs()){
Log.e(TAG, "Failed to create directory.");
return null;
}
}
//3. Create a file name
//4. Create the file
File mediaFile;
Date now = new Date();
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(now);
String path = mediaStorageDir.getPath() + File.separator;
if (mediaType == MEDIA_TYPE_IMAGE){
mediaFile = new File(path + "IMG_" + timestamp + ".jpg");
}
else if (mediaType == MEDIA_TYPE_VIDEO) {
mediaFile = new File(path + "VID_" + timestamp + ".mp4");
} else {
return null;
}
Log.d(TAG, "File: " + Uri.fromFile(mediaFile));
//5. Return the file's URI
return Uri.fromFile(mediaFile);
} else {
return null;
}
}
private boolean isExternalStorageAvailable() {
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)){
return true;
} else {
return false;
}
}
};
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ParseUser currentUser = ParseUser.getCurrentUser();
if (currentUser == null){
navigateToLogin();
} else {
Log.i(TAG, currentUser.getUsername());
}
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK){
if (requestCode == PICK_PHOTO_REQUEST || requestCode == PICK_VIDEO_REQUEST){
if (data == null) {
Toast.makeText(this, getString(R.string.general_error), Toast.LENGTH_LONG).show();
}
else {
mMediaUri = data.getData();
}
Log.i(TAG, "Media UIR: " + mMediaUri);
if (requestCode == PICK_VIDEO_REQUEST) {
// make sure the file is less than 10 MB
int fileSize = 0;
InputStream inputStream = null;
try{
inputStream = getContentResolver().openInputStream(mMediaUri);
fileSize = inputStream.available();
}
catch(FileNotFoundException e) {
Toast.makeText(this, getString(R.string.error_openning_file), Toast.LENGTH_LONG).show();
return;
}
catch(IOException e) {
Toast.makeText(this, getString(R.string.error_openning_file), Toast.LENGTH_LONG).show();
return;
}
finally {
try {
inputStream.close();
} catch (IOException e) {
//Intentionally blank
}
}
if (fileSize >= FILE_SIZE_LIMIT) {
Toast.makeText(this, getString(R.string.error_file_size_too_large), Toast.LENGTH_LONG).show();
return;
}
}
}
else{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(mMediaUri);
sendBroadcast(mediaScanIntent);
}
Intent recipientsIntent = new Intent(this, RecipientsActivity.class);
recipientsIntent.setData(mMediaUri);
String fileType;
if (requestCode == PICK_PHOTO_REQUEST || requestCode == TAKE_PHOTO_REQUEST) {
fileType = ParseConstants.TYPE_IMAGE;
}
else {
fileType = ParseConstants.TYPE_VIDEO;
}
recipientsIntent.putExtra(ParseConstants.KEY_FILE_TYPE, fileType);
startActivity(recipientsIntent);
} else if(resultCode != RESULT_CANCELED){
Toast.makeText(this, R.string.general_error, Toast.LENGTH_LONG).show();
}
}
private void navigateToLogin() {
Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
@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();
switch(id){
case R.id.action_logout:
ParseUser.logOut();
navigateToLogin();
case R.id.action_edit_friends:
Intent intent = new Intent(this, EditFriendsActivity.class);
startActivity(intent);
case R.id.action_camera:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setItems(R.array.camera_choices, mDialogListener);
AlertDialog dialog = builder.create();
dialog.show();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
}
RecipientsActivity.java
public class RecipientsActivity extends ListActivity {
public static final String TAG = RecipientsActivity.class.getSimpleName();
protected ParseRelation<ParseUser> mFriendsRelation;
protected ParseUser mCurrentUser;
protected List<ParseUser> mFriends;
protected MenuItem mSendMenuItem;
protected Uri mMediaUri;
protected String mFileType;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_recipients);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
mMediaUri = getIntent().getData();
mFileType = getIntent().getExtras().getString(ParseConstants.KEY_FILE_TYPE);
}
@Override
public void onResume() {
super.onResume();
mCurrentUser = ParseUser.getCurrentUser();
mFriendsRelation = mCurrentUser.getRelation(ParseConstants.KEY_FRIENDS_RELATION);
setProgressBarIndeterminateVisibility(true);
ParseQuery<ParseUser> query = mFriendsRelation.getQuery();
query.addAscendingOrder(ParseConstants.KEY_USERNAME);
query.findInBackground(new FindCallback<ParseUser>() {
@Override
public void done(List<ParseUser> friends, ParseException e) {
setProgressBarIndeterminateVisibility(false);
if (e == null) {
mFriends = friends;
String[] usernames = new String[mFriends.size()];
int i = 0;
for (ParseUser user : mFriends) {
usernames[i] = user.getUsername();
i++;
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
getListView().getContext(),
android.R.layout.simple_list_item_checked,
usernames);
setListAdapter(adapter);
} else {
//error
Log.e(TAG, e.getMessage());
AlertDialog.Builder builder = new AlertDialog.Builder(RecipientsActivity.this);
builder.setMessage(e.getMessage())
.setTitle(R.string.error_title)
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
});
}
@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_recipients, menu);
mSendMenuItem = menu.getItem(0);
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();
switch (id) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
case R.id.action_send:
ParseObject message = createMessage();
if (message == null) {
//error
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.error_selecting_file))
.setTitle(getString(R.string.error_selecting_file_title))
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
} else {
send(message);
finish();
}
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if (l.getCheckedItemCount() > 0) {
mSendMenuItem.setVisible(true);
}
else {
mSendMenuItem.setVisible(false);
}
}
protected ParseObject createMessage() {
ParseObject message = new ParseObject(ParseConstants.CLASS_MESSAGES);
message.put(ParseConstants.KEY_SENDER_ID, ParseUser.getCurrentUser().getObjectId());
message.put(ParseConstants.KEY_SENDER_NAME, ParseUser.getCurrentUser().getUsername());
message.put(ParseConstants.KEY_RECIPIENT_IDS, getRecipientIds());
message.put(ParseConstants.KEY_FILE_TYPE, mFileType);
byte[] fileBytes = FileHelper.getByteArrayFromFile(this, mMediaUri);
if (fileBytes == null) {
return null;
} else {
if (mFileType.equals(ParseConstants.TYPE_IMAGE)) {
fileBytes = FileHelper.reduceImageForUpload(fileBytes);
}
String fileName = FileHelper.getFileName(this, mMediaUri, mFileType);
ParseFile file = new ParseFile(fileName, fileBytes);
message.put(ParseConstants.KEY_FILE, file);
return message;
}
}
protected ArrayList<String> getRecipientIds() {
ArrayList<String> recipientIds = new ArrayList<String>();
for (int i = 0; i < getListView().getCount(); i++) {
if (getListView().isItemChecked(i)) {
recipientIds.add(mFriends.get(i).getObjectId());
}
}
return recipientIds;
}
protected void send(ParseObject message) {
message.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if (e == null) {
// success!
Toast.makeText(RecipientsActivity.this, getString(R.string.success_message), Toast.LENGTH_LONG).show();
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(RecipientsActivity.this);
builder.setMessage(getString(R.string.error_sending_message))
.setTitle(getString(R.string.error_selecting_file_title))
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
});
}
}
4 Answers
Harry James
14,780 PointsHey Lucian!
What camera app are you using? It it one custom to the S4?
If so, try using a third-party camera like Google Camera and see if it works with this instead.
To reset the default camera, go to Settings >> Apps >> All >> Select your default camera app >> Clear defaults.
Then, next time you click "Take Picture", it will prompt you to select a camera app.
Hope it helps and let me know how it goes :)
L B
28,323 PointsHave you got the correct permissions in your manifest file?
Lucian Thomaz da Silva
9,631 PointsI believe so L B . As I mentioned, what is weird is that if I let the app flows to RecipientsActivity.java and put a break point there I'll get a null value for mMediaUri, but if I put a break point on the MainActivity.java the mMediaUri will get a valid value, and the app will run smoothly with no error.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lucianthomaz.ribbit" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<application
android:name=".RibbitApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".LoginActivity"
android:label="@string/title_activity_login"
android:screenOrientation="portrait" >
</activity>
<activity
android:name=".SignUpActivity"
android:label="@string/title_activity_sign_up"
android:parentActivityName=".MainActivity"
android:screenOrientation="portrait" >
</activity>
<activity
android:name=".EditFriendsActivity"
android:label="@string/title_activity_edit_friends"
android:parentActivityName=".MainActivity"
android:screenOrientation="portrait" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.lucianthomaz.ribbit.MainActivity" />
</activity>
<activity
android:name=".RecipientsActivity"
android:theme="@android:style/Theme.Holo.Light.DarkActionBar"
android:label="@string/title_activity_recipients"
android:screenOrientation="portrait"
android:parentActivityName=".MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.lucianthomaz.ribbit.MainActivity" />
</activity>
</application>
</manifest>
Lucian Thomaz da Silva
9,631 PointsI've just tested on Genymotion and it works fine, with no problem at all. It might be something with my device itself, or the Android version maybe? I'm using 5.0 on my S4, and I've used 4.4 on Genymotion.
Kevin Nguyen
77 PointsHey please tag me when you figure it out. That happens as well on my s4 but another s4 without the new recent update can't take pictures they can only choose.
Kevin Nguyen
77 PointsHarry James Thanks a bunch for helping me with all the other problems. This is the link that has the app crashes. I will post my code in as well for main activity and recipients. When I click take photo it works and takes me to the Recipients activity. From there when I try to send that photo that was taken via the app it will crash..only for 5.0 though...it works find with an s4 that is running kitkat verison.
I have read this form http://stackoverflow.com/questions/29145976/android-lollipop-camera-issue as well
package com.thegreathoudini.kevin.odysity;
import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.support.v4.app.FragmentTransaction; import android.support.v4.app.FragmentPagerAdapter; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.Window; import android.widget.Toast;
import com.parse.ParseAnalytics; import com.parse.ParseUser;
import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale;
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener {
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
public static final String TAG = MainActivity.class.getSimpleName();
public static final int TAKE_PHOTO_REQUEST_CODE = 1;
public static final int CHOOSE_PHOTO_REQUEST_CODE = 100;
public static final int CHOOSE_DEFAULT_PICTURE_CODE = 200;
protected static final int MEDIA_TYPE_IMAGE = 400;
protected Uri mMediaUri;
protected DialogInterface.OnClickListener mDialoglistener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which){
case 0://Take Picture
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
mMediaUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
if(mMediaUri == null){
Toast.makeText(MainActivity.this, R.string.camera_external_toast, Toast.LENGTH_LONG).show();
}
else{
takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, mMediaUri);
startActivityForResult(takePhotoIntent, TAKE_PHOTO_REQUEST_CODE);
}
break;
case 1: //Choose Picture
Intent choosePhotoIntent = new Intent(Intent.ACTION_GET_CONTENT);
choosePhotoIntent.setType("image/*");
startActivityForResult(choosePhotoIntent, CHOOSE_PHOTO_REQUEST_CODE);
break;
case 2: //Change Default Picture
Intent changeDefaultPicture = new Intent(Intent.ACTION_GET_CONTENT);
changeDefaultPicture.setType("image/*");
startActivityForResult(changeDefaultPicture, CHOOSE_DEFAULT_PICTURE_CODE);
break;
}
}
private Uri getOutputMediaFileUri(int mediaType) {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
//http://developer.android.com/guide/topics/media/camera.html#saving-media
if(isExternalStorageAvailable()){
//Get Uri
String appname = MainActivity.this.getString(R.string.app_name);
// 1) Get the External storage directory
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), appname);
// 2) Create our subdirectory
if(! mediaStorageDir.exists()){
if(!mediaStorageDir.mkdir()){
Log.e(TAG, "Failed to make Dir");
return null;
}
}
// 3) Create our file name
// 4) Create the file
File mediaFile;
Date now = new Date();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(now);
String path = mediaStorageDir.getPath() + File.separator;
if(mediaType == MEDIA_TYPE_IMAGE){
mediaFile = new File(path +"IMG_"+ timeStamp + ".jpg");
}
else {
return null;
}
Log.d(TAG,"File: " + Uri.fromFile(mediaFile));
// 5) Return files Uri
return Uri.fromFile(mediaFile);
}
else {
return null;
}
}
private boolean isExternalStorageAvailable(){
String state = Environment.getExternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED)){
return true;
}
else {
return false;
}
}
};
/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Parse analytics tool.
ParseAnalytics.trackAppOpenedInBackground(getIntent());
ParseUser currentUser = ParseUser.getCurrentUser();
if(currentUser == null)
{
navigateToLogin();
}
else{
//Log.i
Log.i(TAG, currentUser.getUsername());
}
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
if(requestCode == CHOOSE_PHOTO_REQUEST_CODE){
if(data == null){
//error
Toast.makeText(this, R.string.general_error, Toast.LENGTH_LONG).show();
}
else{
mMediaUri = data.getData();
}
}
else {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(mMediaUri);
sendBroadcast(mediaScanIntent);
}
Intent recipientsIntent = new Intent(this, RecipientsActivity.class);
recipientsIntent.setData(mMediaUri);
String fileType = null;
if(requestCode == TAKE_PHOTO_REQUEST_CODE || requestCode == CHOOSE_PHOTO_REQUEST_CODE) {
fileType = ParseConstants.TYPE_IMAGE;
}
recipientsIntent.putExtra(ParseConstants.KEY_FILE_TYPE, fileType);
startActivity(recipientsIntent);
}
else if(resultCode != RESULT_CANCELED){
Toast.makeText(MainActivity.this, R.string.general_error, Toast.LENGTH_LONG).show();
}
}
private void navigateToLogin() {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
@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();
switch(id){
case R.id.logoutMenu:
ParseUser.logOutInBackground();
navigateToLogin();
break;
case R.id.editFriendsMenu:
Intent intent = new Intent(this, EditFriendsActivity.class);
startActivity(intent);
break;
case R.id.camera_menu:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setItems(R.array.camera_Choices, mDialoglistener);
AlertDialog dialog = builder.create();
dialog.show();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
}
package com.thegreathoudini.kevin.odysity;
import android.app.AlertDialog; import android.app.ListActivity; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.Toast;
import com.parse.FindCallback; import com.parse.ParseException; import com.parse.ParseFile; import com.parse.ParseInstallation; import com.parse.ParseObject; import com.parse.ParsePush; import com.parse.ParseQuery; import com.parse.ParseRelation; import com.parse.ParseUser; import com.parse.SaveCallback;
import java.util.ArrayList; import java.util.List;
public class RecipientsActivity extends ListActivity {
public static final String TAG = RecipientsActivity.class.getSimpleName();
protected ParseRelation<ParseUser> mFriendsRelations;
protected ParseUser mCurrentUser;
protected List<ParseUser> mFriends;
protected ProgressBar mLoadingRecipients;
protected MenuItem mSendMenuItem;
protected Uri mMediaUri;
protected String mFileType;
protected EditText mCommentText;
protected String mComment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recipients);
getActionBar();
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
mMediaUri = getIntent().getData();
mFileType = getIntent().getExtras().getString(ParseConstants.KEY_FILE_TYPE);
}
@Override
protected void onResume() {
super.onResume();
mCommentText = (EditText) findViewById(R.id.commentEditText);
mLoadingRecipients = (ProgressBar) findViewById(R.id.loadingRecipientsProgress);
mCurrentUser = ParseUser.getCurrentUser();
mFriendsRelations = mCurrentUser.getRelation(ParseConstants.KEY_Friends_Relations);
mLoadingRecipients.setVisibility(View.VISIBLE);
ParseQuery<ParseUser> query = mFriendsRelations.getQuery();
query.orderByAscending(ParseConstants.KEY_USERNAME);
query.setCachePolicy(ParseQuery.CachePolicy.CACHE_THEN_NETWORK);
query.setLimit(1000);
query.findInBackground(new FindCallback<ParseUser>() {
@Override
public void done(List<ParseUser> friends, ParseException e) {
//Build the list of Parse relations
mLoadingRecipients.setVisibility(View.INVISIBLE);
if (e == null) {
mFriends = friends;
String[] friendsUsername = new String[mFriends.size()];
int i = 0;
for (ParseUser friendlist : mFriends) {
friendsUsername[i] = friendlist.get(ParseConstants.KEY_NAME).toString();
i++;
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
RecipientsActivity.this, android.R.layout.simple_list_item_checked, friendsUsername);
setListAdapter(adapter);
}
} else {
mLoadingRecipients.setVisibility(View.INVISIBLE);
Log.e(TAG, e.getMessage());
AlertDialog.Builder builder = new AlertDialog.Builder(RecipientsActivity.this);
builder.setTitle(R.string.signup_error_title)
.setMessage(R.string.no_friends_found)
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
});
}
@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_recipients, menu);
mSendMenuItem = menu.getItem(0);
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_send) {
mComment = mCommentText.getText().toString();
if(mComment.isEmpty()){
mComment = "";
}
mLoadingRecipients.setVisibility(View.VISIBLE);
ParseObject message = createMessage();
if(message == null){
//error
mLoadingRecipients.setVisibility(View.INVISIBLE);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.error_file)
.setTitle(R.string.signup_error_title)
.setPositiveButton(android.R.string.ok,null);
AlertDialog dialog = builder.create();
dialog.show();
}
else {
Toast.makeText(RecipientsActivity.this, R.string.sending_message_toast, Toast.LENGTH_LONG).show();
send(message);
mLoadingRecipients.setVisibility(View.INVISIBLE);
finish();
}
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if(l.getCheckedItemCount() > 0){
mSendMenuItem.setVisible(true);
}
else {
mSendMenuItem.setVisible(false);
}
}
protected ParseObject createMessage(){
ParseObject message = new ParseObject(ParseConstants.CLASS_MESSAGES);
message.put(ParseConstants.KEY_SENDERS_IDS , ParseUser.getCurrentUser().getObjectId());
message.put(ParseConstants.KEY_SENDER_NAME , ParseUser.getCurrentUser().get(ParseConstants.KEY_NAME));
message.put(ParseConstants.KEY_RECIPIENTS_IDS, getRecipientsIds());
message.put(ParseConstants.KEY_FILE_TYPE, mFileType);
message.put(ParseConstants.KEY_COMMENT_TEXT, mComment);
byte[] fileByte = FileHelper.getByteArrayFromFile(this, mMediaUri);
if(fileByte == null){
return null;
}
else {
if (mFileType.equals(ParseConstants.TYPE_IMAGE)){
fileByte = FileHelper.reduceImageForUpload(fileByte);
}
String fileName = FileHelper.getFileName(this, mMediaUri,mFileType);
ParseFile file = new ParseFile(fileName, fileByte);
message.put(ParseConstants.KEY_FILE, file);
return message;
}
}
protected ArrayList<String> getRecipientsIds(){
ArrayList<String> recipientsList = new ArrayList<>();
for(int i = 0; i<getListView().getCount() ; i++){
if(getListView().isItemChecked(i)){
recipientsList.add(mFriends.get(i).getObjectId());
}
}
return recipientsList;
}
protected void send(ParseObject message){
message.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if (e == null) {
//success
Toast.makeText(RecipientsActivity.this, R.string.success_message, Toast.LENGTH_LONG).show();
sendPushNotification();
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(RecipientsActivity.this);
builder.setMessage(R.string.error_file)
.setTitle(R.string.signup_error_title)
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
});
}
protected void sendPushNotification (){
ParseQuery<ParseInstallation> query = ParseInstallation.getQuery();
query.whereContainedIn(ParseConstants.KEY_USER_ID, getRecipientsIds());
//send push notification
ParsePush push = new ParsePush();
push.setQuery(query);
push.setMessage(getString(R.string.push_string , ParseUser.getCurrentUser().get(ParseConstants.KEY_NAME)));
push.sendInBackground();
}
}
Lucian Thomaz da Silva
9,631 PointsKevin Nguyen I'm not really looking for the solution because it works in my emulator, so I decided to move on with the rest of the project, but if I find the solution I'll share it for sure. If you find an answer please share with me as well. :)
Lucian Thomaz da Silva
9,631 PointsLucian Thomaz da Silva
9,631 PointsIt works Harry James :D . Did not even went through my mind that it could do the trick. Thank you.
Harry James
14,780 PointsHarry James
14,780 PointsWoohoo! Glad it's working! To me, it sounds like the Camera app used by your phone isn't correctly responding to the intents we give it and so, the app crashes.
This would be at fault of the camera app developers however, so there's nothing we can do to fix the issue (Unless we were to use the Camera without an Intent).