On my on create function I give the location an ID. However my issue is when I go to add a photo to that page before I've saved it. I need to save the photo with the same ID as the page. So I create the ID on the on create then when i add a picture and come back as it's loaded the other intent it runs the code again and creates a new ID. How can I pass the ID through the photo and back.
The variable checkStationObjectID is set at the top of the file.
Heres my on create:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_asset);
Bundle extras = getIntent().getExtras();
Log.e("CamDebug", "Loading extras");
if (extras != null) {
PreviousStationObjectID = extras.getString("StationObjectID");
editMode = extras.getBoolean("editMode");
editAreaObjectID = extras.getString("editAreaObjectID");
}
if(editMode){
checkStationObjectID = editAreaObjectID;
Log.e("CHECK ID - Edit mode", checkStationObjectID);
} else {
if(checkStationObjectID == null){
checkStationObjectID = NewAssetStationObjectID;
Log.e("CHECK ID = NEW ID", checkStationObjectID);
}
}
//Other items taken out
}
I launch the camera with:
public void startCamera()
{
File photo = null;
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
{
photo = new File(Global.Pictures + timestamp +".png");
}
else
{
photo = new File(getCacheDir(), FOLDER_NAME+File.separator+timestamp+".png");
}
if (photo != null)
{
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
selectedImageUri = Uri.fromFile(photo);
startActivityForResult(intent, CAPTURE_IMAGE_CALLBACK);
}
}
onCreate is called whenever your application is started. If you are calling another app like a camera, then the OS can kill your own Activity at any time while the camera Activity is running. This could be to recover memory or resources that the running app needs. Then when you exit the camera the OS will restart your Activity, which will call onCreate again.
I would suggest that you save the ID that you have generated into SharedPreferences just before you start the camera app. Then check for a saved ID in onActivityResult.
If you don't need to persist it you can create a Singleton object to act as a session and store the variable in there.. But I don't get why onCreate is executed again.. I thought the sub camera activity should return in onActivityResult? I pardon me if I misunderstood.
Or you can pass the var to the camera activity and pass it back when you are done with it.
Related
I am using a webrtc sample Code to stream from my Android device to a Webpage.
The sample Code does not have the function to Switch the camera. I tried to solve it but I failed. The sample uses a VideoCapturerAndroid class all of the Suggestions I found switching the camera used a different type.
The main part of the sample Looks like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_chat);
ButterKnife.bind(this);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Bundle extras = getIntent().getExtras();
if (extras == null || !extras.containsKey(Constants.USER_NAME)) {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
Toast.makeText(this, "Need to pass username to VideoChatActivity in intent extras (Constants.USER_NAME).", Toast.LENGTH_SHORT).show();
finish();
return;
}
this.username = extras.getString(Constants.USER_NAME, "");
this.mCallStatus = (TextView) findViewById(R.id.call_status);
// First, we initiate the PeerConnectionFactory with our application context and some options.
PeerConnectionFactory.initializeAndroidGlobals(
this, // Context
true, // Audio Enabled
true, // Video Enabled
true, // Hardware Acceleration Enabled
null); // Render EGL Context
pcFactory = new PeerConnectionFactory();
this.pnRTCClient = new PnRTCClient(Constants.PUB_KEY, Constants.SUB_KEY, this.username);
List<PeerConnection.IceServer> servers = getXirSysIceServers();
if (!servers.isEmpty()) {
this.pnRTCClient.setSignalParams(new de.kevingleason.pnwebrtc.PnSignalingParams());
}
backFacingCam = VideoCapturerAndroid.getNameOfBackFacingDevice();
frontFacingCam = VideoCapturerAndroid.getNameOfFrontFacingDevice();
// Creates a VideoCapturerAndroid instance for the device name
//VideoCapturer capturer = VideoCapturerAndroid.create(frontFacingCam);
capturer = VideoCapturerAndroid.create(facingCam);
// First create a Video Source, then we can make a Video Track
localVideoSource = pcFactory.createVideoSource(capturer, this.pnRTCClient.videoConstraints());
localVideoTrack = pcFactory.createVideoTrack(VIDEO_TRACK_ID, localVideoSource);
// First we create an AudioSource then we can create our AudioTrack
AudioSource audioSource = pcFactory.createAudioSource(this.pnRTCClient.audioConstraints());
AudioTrack localAudioTrack = pcFactory.createAudioTrack(AUDIO_TRACK_ID, audioSource);
// To create our VideoRenderer, we can use the included VideoRendererGui for simplicity
// First we need to set the GLSurfaceView that it should render to
this.videoView = (GLSurfaceView) findViewById(R.id.gl_surface);
// Then we set that view, and pass a Runnable to run once the surface is ready
VideoRendererGui.setView(videoView, null);
// Now that VideoRendererGui is ready, we can get our VideoRenderer.
// IN THIS ORDER. Effects which is on top or bottom
remoteRender = VideoRendererGui.create(0, 0, 100, 100, VideoRendererGui.ScalingType.SCALE_ASPECT_FILL, false);
localRender = VideoRendererGui.create(0, 0, 100, 100, VideoRendererGui.ScalingType.SCALE_ASPECT_FILL, true);
// We start out with an empty MediaStream object, created with help from our PeerConnectionFactory
// Note that LOCAL_MEDIA_STREAM_ID can be any string
MediaStream mediaStream = pcFactory.createLocalMediaStream(LOCAL_MEDIA_STREAM_ID);
// Now we can add our tracks.
mediaStream.addTrack(localVideoTrack);
mediaStream.addTrack(localAudioTrack);
// First attach the RTC Listener so that callback events will be triggered
this.pnRTCClient.attachRTCListener(new DemoRTCListener());
// Then attach your local media stream to the PnRTCClient.
// This will trigger the onLocalStream callback.
this.pnRTCClient.attachLocalMediaStream(mediaStream);
this.pnRTCClient.listenOn(username);
this.pnRTCClient.setMaxConnections(1);
....
}
Currently I am hardcoding which camera shall be used:
backFacingCam = VideoCapturerAndroid.getNameOfBackFacingDevice();
frontFacingCam = VideoCapturerAndroid.getNameOfFrontFacingDevice();
This is my button which shall Switch the camera:
#OnClick(R.id.switchCameraBtn)
public void switchCameraBtn(View view) {
Log.e("Test", "switch camera button clicked");
this.mCallStatus = (TextView) findViewById(R.id.call_status);
}
I also tried to restart the activity and give a Parameter which tells one that the other camera shall be used, but I would like to Keep the stream fluent and not to restart the activity.
You are using a very old implementation of WebRTC in android. VideoRendererGui is removed from new WebRTC library. I strongly suggest you to always use the newest version possible of google WebRTC from here which is at the time of writing is 1.0.22512
compile 'org.webrtc:google-webrtc:1.0.22512'
You can check the Android implementation of the newest library from official WebRTC Chromium project site here. Check out the other classes too.
With the new library, you should create a VideoCapturer in the following way.
private void createVideoCapturer() {
VideoCapturer videoCapturer;
if (Camera2Enumerator.isSupported(this)) {
videoCapturer = createCameraCapturer(new Camera2Enumerator(this));
} else {
videoCapturer = createCameraCapturer(new Camera1Enumerator(false));
}
}
createCameraCapturer() Method :
private VideoCapturer createCameraCapturer(CameraEnumerator enumerator) {
final String[] deviceNames = enumerator.getDeviceNames();
// First, try to find front facing camera
for (String deviceName : deviceNames) {
if (enumerator.isFrontFacing(deviceName)) {
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
return videoCapturer;
}
}
}
// Front facing camera not found, try something else
for (String deviceName : deviceNames) {
if (!enumerator.isFrontFacing(deviceName)) {
CameraVideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
return videoCapturer;
}
}
}
return null;
}
and call switchCamera() method from your class whenever you want to switch between front and back camera.
private void switchCamera() {
if (videoCapturer != null) {
if (videoCapturer instanceof CameraVideoCapturer) {
CameraVideoCapturer cameraVideoCapturer = (CameraVideoCapturer) videoCapturer;
cameraVideoCapturer.switchCamera(null);
} else {
// Will not switch camera, video capturer is not a camera
}
}
}
I am trying to capture an image and then display it on the screen using another activity. I am able to successfully capture the images and save them in my desired directory. However, even after hours of struggle, I am still unable to solve this problem. The touch listener is added to the screen though there's no image.
Here's the code:
private void takeImage(){ Intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "MyImages");
imagesFolder.mkdirs();
File image = new File(imagesFolder, "QR_" + timeStamp + ".png");
Uri uriSavedImage = Uri.fromFile(image);
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
startActivityForResult(imageIntent, PHOTO_TAKEN); }
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PHOTO_TAKEN){
data.putExtra(SET_CAPTURED_IMAGE, true);
} else{
Log.d(MainActivity.DEBUGTAG, "Photo = null");
}
}
Now in another activity (ImageActivity):
addTouchListener() is called in onCreate() method of this activity.
Till here, the image is successfully captured and saved in the directory.
private void addTouchListener(){
ImageView imageView = (ImageView)findViewById(R.id.unlocker_image);
Bundle extras = getIntent().getExtras();
//The following if block is not executed
if (extras != null && extras.getBoolean(MainActivity.SET_CAPTURED_IMAGE)){
Uri imageUri= Uri.parse(extras.getString(MediaStore.EXTRA_OUTPUT));
imageView.setImageURI(imageUri);
} else {
imageView.setImageResource(R.drawable.unlocker_image);
//this is the default image added
}
imageView.setOnTouchListener(collector);
}
At this point, the touch listener is added but there's no image.
I have a main activity, in which the user is shown a dialogue to pick an image from the gallery or use the camera. The problem is ( I think ) that i'm building against the 6.0 APIs and the permissions are what's messing me up.
When the application passes the Uri (As a string) into a database, the Adapter has to access that database and get the picture and put it into an ImageView.
I get the READ_EXTERNAL_STORAGE permission to access the file in the MainActivity, but I think I also need it in the adapter, but I can't access permissions from in there.
//TL;DR how can I access the internal storage (pictures) from inside of a recyclerview adapter class?
Here's my code:
After I check for permissions, I start the intent to pick the image:
//RESULT_LOAD_IMAGE = 0;
Intent toGal = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(toGal, RESULT_LOAD_IMAGE);
then, inside of the onActivityResult, I get the URI and set a variable to it's string value
boolean request = requestCode == RESULT_LOAD_CAMER || requestCode == RESULT_LOAD_IMAGE;
if (resultCode == Activity.RESULT_OK && request && imageReturnedIntent != null) {
Uri selectedImage = imageReturnedIntent.getData();
picturePath = String.valueOf(selectedImage);
Log.i(TAG, picturePath);
}
And then I store it in a Realm database, and access it from the adapter. I know this is not the problem, because I can log the path that was stored in the db that points to the image just fine.
Here is where I access it inside of the Adapter:
String imgString = Model.getImage(); //This is "/emulated/storage/pathtoimg.jpg"
if (imgString != null) {
Bitmap BM = BitmapFactory.decodeFile(imgString);
ImageView.setImageBitmap(BM);
}
}
But nothing happens. When I try to request permissions from inside the Adapter it says it needs to be an activity so how can I access the internal storage from a recyclerview adapter?
I'm making an android application which uses it's own Camera activity. The images are then stored on the local SQLite database by using an IntentService.
Problem now is: the IntentService doesn't get started after the picture is taken. When using this IntentService on other occations it works perfect so I am at a loss on the why it is not working...
Below is the code used in my CameraActivity to take a picture and start the IntentService.
mPicture = getPictureCallback();
mRaw = getRawCallback();
mShutter = getShutterCallback();
mCamera.takePicture(mShutter, mRaw, mPicture);
private PictureCallback getPictureCallback() {
PictureCallback picture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.d(LOG_TAG, "Picture taken, starting service");
Intent databaseIntent = new Intent(MyCameraActivity.this, DBHandlerService.class);
databaseIntent.putExtra("image", data);
databaseIntent.putExtra("action", "save");
databaseIntent.putExtra(AppConstant.RESULT_RECEIVER, mReceiver);
startService(databaseIntent);
mPreview.refreshCamera(mCamera);
}
};
return picture;
}
The onHandleEvent:
#Override
protected void onHandleIntent(Intent intent) {
Log.d(LOG_TAG, "onHandle started");
Database db = getDB();
action = intent.getStringExtra("action");
Bundle resultbundle = new Bundle();
Log.d(LOG_TAG, "onHandleIntent action : " + action);
final ResultReceiver reciever = intent
.getParcelableExtra(AppConstant.RESULT_RECEIVER);
reciever.send(STATUS_RUNNING, Bundle.EMPTY);
//Different actions depending on the "action" string
if(action.equals("xxxxx"){
//perform action
} else {
// inform activity the requested action does not exist. When
// STATUS_ERROR is received they must check if errorcode is not
// null.
resultbundle.putString("errormsg", "No actions undertaken");
resultbundle.putInt("errorcode", 9999);
reciever.send(STATUS_ERROR, resultbundle);
}
}
I also use this IntentService to get all the pictures from the database. Since the DB stays empty no images are returned but every log gets printed.
If i try it to save the image the logs inside the IntentService are nevr printed.
If more code is needed, let me know.
Thanks in advance!
Thomas
I am learning android and curious to know as if startActivityForResult() contains the properties of startActivity() too, i.e. can it be used to send data like startActivity() beside receiving data from called activity?
Here is the code:
SendData Activity:
Intent data= new Intent(SendData.this, RecieveData.class);
Bundle check = new Bundle();
check.putString("UmerData", cheese);
medt.setText(cheese);
data.putExtras(check);
startActivityForResult(data, 5);
Should receive data in this activity (RecieveData Activity)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recievedata);
Initializek();
Bundle got = getIntent().getExtras();
String ss= got.getString("UmerData");
if(getIntent()!=null && ss!=null ) {
rt1.setText("Is not Null");
}
}
Your help will be really appreciated !
Thanks
Yes, startActivity & startActivityForResult, both take intent as param. You can bundle launch data inside intent and pass it over to target activity.
When you use startActivityForResult(), you have to also create a onActivityResult() method within the Activity that called startActivityForResult(). onActivityResult() is where you can access the Intent stored by the Activity you start for a result.
In the Activity that is then started, you have to call setResult() to store the Intent that you store the data in.
Read over this: http://developer.android.com/reference/android/app/Activity.html#StartingActivities
edit: Misread your question. For passing a Bundle of options through, I would use this overload:
startActivity(Intent, int, Bundle)
I'm working in Xamarin Android so the code is C# but I had the same problem except I'm sending between separate apps. I eventually got it working so here is my example.
var intent = new Intent();
intent.SetComponent(new ComponentName("com.company.packageName", "com.company.packageName.activityName"));
intent.PutExtra(Intent.ExtraText, message);
StartActivityForResult(intent, 1);
// in app being started
protected override void OnResume()
{
base.OnResume();
Intent intent = Intent; // Equivalent to getIntent()
if (intent != null)
{
string str = intent.GetStringExtra(Intent.ExtraText);
if (str != null)
{
// Do stuff with str
}
else
{
//Show Error
}
}
else
{
//Show Error
}
}