Getting result from startActivityForResult inside BroadcastReciever, calling ACTION_INSTALL_PACKAGE Intent - java

I am creating an app from which the user can download other apps and install them. Right now it works fine, but It does not delete the apk after the installation. I have tried using BroadcastRecievers but they do not seem to understand when the application is already installed.
At the moment I am trying to startActivityForResult and once that is finished, delete the apk from Files.
public class Updater {
private static BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Logger.d("Download completed.");
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(), downloadApp.getDownloadKey());
Logger.i("Opening: " + file.getAbsolutePath());
Intent openDownloadIntent = getOpenDownloadedApkIntent(context, file);
RelativeLayout progressView = progressViewReference.get();
if (progressView!= null) {
progressView.setVisibility(View.GONE);
}
try {
((Activity) context).startActivityForResult(openDownloadIntent, getResultCode());
} catch (ActivityNotFoundException e) {
// TODO: more robust error handling (show dialog or something)
Logger.e("Exception when launching download intent, message:" + e.getMessage());
}
}
};
private static Intent getOpenDownloadedApkIntent(Context context, File file) {
// The type of intent to use to open the downloaded apk changed in Android N (7.0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri path = FileProvider.getUriForFile(context,
context.getApplicationContext().getPackageName() + ".utils.DownloadedFileProvider",
file);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setData(path);
return intent;
} else {
Uri uri = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
return intent;
}
}
}
So I have the Updater class where the 2 methods are (see my code above). And this class is being called by an adapter, so there is nowhere to put the onActivityResult. I tried placing it in the Activity that calls the Adapter, which calls the Updater class but it does not reach there even with the EXTRA_RETURN_RESULT
So my question is.. how can I call onActivityResult here once the installation is finished.

this is pseudo code for you activity
class DownloadActivity extends AppCompatActivity {
// some of your code here
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
// in here you are checking if requestCode is equal to Intent.ACTION_INSTALL_PACKAGE
if(requestCode == Intent.ACTION_INSTALL_PACKAGE and resultCode == ResultCode.OK) {
// Start activity for deleting file
startActivityForResult(Intente.ACTION_DELETE);
}
if(requestCode == Intent.ACTION_DELETE and resultCode == ResultCode.OK) {
// Handling actions after deleted
}
}
}
OnActivityResult is called by android, when action is ended. You do not have to call this method only inside this method you define what have to be done.
Where those onDownloadComplete and getOpenDownloadedApkIntent are defined and called?

Related

How to pass a callback method between Xamarin Android activites [duplicate]

In my activity, I'm calling a second activity from the main activity by startActivityForResult. In my second activity, there are some methods that finish this activity (maybe without a result), however, just one of them returns a result.
For example, from the main activity, I call a second one. In this activity, I'm checking some features of a handset, such as does it have a camera. If it doesn't have then I'll close this activity. Also, during the preparation of MediaRecorder or MediaPlayer if a problem happens then I'll close this activity.
If its device has a camera and recording is done completely, then after recording a video if a user clicks on the done button then I'll send the result (address of the recorded video) back to the main activity.
How do I check the result from the main activity?
From your FirstActivity, call the SecondActivity using the startActivityForResult() method.
For example:
int LAUNCH_SECOND_ACTIVITY = 1
Intent i = new Intent(this, SecondActivity.class);
startActivityForResult(i, LAUNCH_SECOND_ACTIVITY);
In your SecondActivity, set the data which you want to return back to FirstActivity. If you don't want to return back, don't set any.
For example: In SecondActivity if you want to send back data:
Intent returnIntent = new Intent();
returnIntent.putExtra("result",result);
setResult(Activity.RESULT_OK,returnIntent);
finish();
If you don't want to return data:
Intent returnIntent = new Intent();
setResult(Activity.RESULT_CANCELED, returnIntent);
finish();
Now in your FirstActivity class, write the following code for the onActivityResult() method.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LAUNCH_SECOND_ACTIVITY) {
if(resultCode == Activity.RESULT_OK){
String result=data.getStringExtra("result");
}
if (resultCode == Activity.RESULT_CANCELED) {
// Write your code if there's no result
}
}
} //onActivityResult
To implement passing data between two activities in a much better way in Kotlin, please go through 'A better way to pass data between Activities'.
How to check the result from the main activity?
You need to override Activity.onActivityResult() and then check its parameters:
requestCode identifies which app returned these results. This is defined by you when you call startActivityForResult().
resultCode informs you whether this app succeeded, failed, or something different
data holds any information returned by this app. This may be null.
Example
To see the entire process in context, here is a supplemental answer. See my fuller answer for more explanation.
MainActivity.java
public class MainActivity extends AppCompatActivity {
// Add a different request code for every activity you are starting from here
private static final int SECOND_ACTIVITY_REQUEST_CODE = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// "Go to Second Activity" button click
public void onButtonClick(View view) {
// Start the SecondActivity
Intent intent = new Intent(this, SecondActivity.class);
startActivityForResult(intent, SECOND_ACTIVITY_REQUEST_CODE);
}
// This method is called when the second activity finishes
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// check that it is the SecondActivity with an OK result
if (requestCode == SECOND_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) { // Activity.RESULT_OK
// get String data from Intent
String returnString = data.getStringExtra("keyName");
// set text view with string
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(returnString);
}
}
}
}
SecondActivity.java
public class SecondActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
// "Send text back" button click
public void onButtonClick(View view) {
// get the text from the EditText
EditText editText = (EditText) findViewById(R.id.editText);
String stringToPassBack = editText.getText().toString();
// put the String to pass back into an Intent and close this activity
Intent intent = new Intent();
intent.putExtra("keyName", stringToPassBack);
setResult(RESULT_OK, intent);
finish();
}
}
Complementing the answer from Nishant, the best way to return the activity result is:
Intent returnIntent = getIntent();
returnIntent.putExtra("result",result);
setResult(RESULT_OK,returnIntent);
finish();
I was having a problem with
new Intent();
Then I found out that the correct way is using
getIntent();
to get the current intent.
startActivityForResult: Deprecated in Android X
For the new way we have registerForActivityResult.
In Java :
// You need to create a launcher variable inside onAttach or onCreate or global, i.e, before the activity is displayed
ActivityResultLauncher<Intent> launchSomeActivity = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
// your operation....
}
}
});
public void openYourActivity() {
Intent intent = new Intent(this, SomeActivity.class);
launchSomeActivity.launch(intent);
}
In Kotlin :
var resultLauncher = registerForActivityResult(StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data: Intent? = result.data
// your operation...
}
}
fun openYourActivity() {
val intent = Intent(this, SomeActivity::class.java)
resultLauncher.launch(intent)
}
Advantage:
The new way is reduce complexity which we faced when we call the activity from a fragment or from another activity
Easily ask for any permission and get callback
For those who have problem with wrong requestCode in onActivityResult
If you are calling startActivityForResult() from your Fragment, the requestCode is changed by the Activity that owns the Fragment.
If you want to get the correct resultCode in your activity try this:
Change:
startActivityForResult(intent, 1); To:
getActivity().startActivityForResult(intent, 1);
The ActivityResultRegistry is the recommended approach
ComponentActivity now provides an ActivityResultRegistry that lets you handle the startActivityForResult()+onActivityResult() as well as requestPermissions()+onRequestPermissionsResult() flows without overriding methods in your Activity or Fragment, brings increased type safety via ActivityResultContract, and provides hooks for testing these flows.
It is strongly recommended to use the Activity Result APIs introduced in Android 10 Activity 1.2.0-alpha02 and Fragment 1.3.0-alpha02.
Add this to your build.gradle
def activity_version = "1.2.0-beta01"
// Java language implementation
implementation "androidx.activity:activity:$activity_version"
// Kotlin
implementation "androidx.activity:activity-ktx:$activity_version"
How to use the pre-built contract
This new API has the following pre-built functionalities
TakeVideo
PickContact
GetContent
GetContents
OpenDocument
OpenDocuments
OpenDocumentTree
CreateDocument
Dial
TakePicture
RequestPermission
RequestPermissions
An example that uses the takePicture contract:
private val takePicture = prepareCall(ActivityResultContracts.TakePicture()) { bitmap: Bitmap? ->
// Do something with the Bitmap, if present
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener { takePicture() }
}
So what’s going on here? Let’s break it down slightly. takePicture is just a callback which returns a nullable Bitmap - whether or not it’s null depends on whether or not the onActivityResult process was successful. prepareCall then registers this call into a new feature on ComponentActivity called the ActivityResultRegistry - we’ll come back to this later. ActivityResultContracts.TakePicture() is one of the built-in helpers which Google have created for us, and finally invoking takePicture actually triggers the Intent in the same way that you would previously with Activity.startActivityForResult(intent, REQUEST_CODE).
How to write a custom contract
A simple contract that takes an Int as an input and returns a string that the requested Activity returns in the result Intent.
class MyContract : ActivityResultContract<Int, String>() {
companion object {
const val ACTION = "com.myapp.action.MY_ACTION"
const val INPUT_INT = "input_int"
const val OUTPUT_STRING = "output_string"
}
override fun createIntent(input: Int): Intent {
return Intent(ACTION)
.apply { putExtra(INPUT_INT, input) }
}
override fun parseResult(resultCode: Int, intent: Intent?): String? {
return when (resultCode) {
Activity.RESULT_OK -> intent?.getStringExtra(OUTPUT_STRING)
else -> null
}
}
}
class MyActivity : AppCompatActivity() {
private val myActionCall = prepareCall(MyContract()) { result ->
Log.i("MyActivity", "Obtained result: $result")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
button.setOnClickListener {
myActionCall(500)
}
}
}
Check this official documentation for more information.
If you want to update the user interface with the activity result, you can't to use this.runOnUiThread(new Runnable() {}. Doing this, the UI won't refresh with the new value. Instead, you can do this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
return;
}
global_lat = data.getDoubleExtra("LATITUDE", 0);
global_lng = data.getDoubleExtra("LONGITUDE", 0);
new_latlng = true;
}
#Override
protected void onResume() {
super.onResume();
if(new_latlng)
{
PhysicalTagProperties.this.setLocation(global_lat, global_lng);
new_latlng=false;
}
}
This seems silly, but it works pretty well.
In Kotlin
Suppose A & B are activities the navigation is from A -> B
We need the result back from A <- B
in A
// calling the Activity B
resultLauncher.launch(Intent(requireContext(), B::class.java))
// we get data in here from B
private var resultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
when (result.resultCode) {
Activity.RESULT_OK -> {
result.data?.getStringExtra("VALUE")?.let {
// data received here
}
}
Activity.RESULT_CANCELED -> {
// cancel or failure
}
}
}
In B
// Sending result value back to A
if (success) {
setResult(RESULT_OK, Intent().putExtra("VALUE", value))
} else {
setResult(RESULT_CANCELED)
}
It is a very common problem on Android
It can be broken down into three pieces
Start Activity B (happens in Activity A)
Set requested data (happens in activity B)
Receive requested data (happens in activity A)
startActivity B
Intent i = new Intent(A.this, B.class);
startActivity(i);
Set requested data
In this part, you decide whether you want to send data back or not when a particular event occurs.
E.g.: In activity B there is an EditText and two buttons b1, b2.
Clicking on Button b1 sends data back to activity A.
Clicking on Button b2 does not send any data.
Sending data
b1......clickListener
{
Intent resultIntent = new Intent();
resultIntent.putExtra("Your_key", "Your_value");
setResult(RES_CODE_A, resultIntent);
finish();
}
Not sending data
b2......clickListener
{
setResult(RES_CODE_B, new Intent());
finish();
}
The user clicks the back button
By default, the result is set with Activity.RESULT_CANCEL response code
Retrieve result
For that override onActivityResult method
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RES_CODE_A) {
// b1 was clicked
String x = data.getStringExtra("RES_CODE_A");
}
else if(resultCode == RES_CODE_B){
// b2 was clicked
}
else{
// The back button was clicked
}
}
I will post the new "way" with Android X in a short answer (because in some case you does not need custom registry or contract). If you want more information, see: Getting a result from an activity
Important: there is actually a bug with the backward compatibility of Android X so you have to add fragment_version in your Gradle file. Otherwise you will get an exception "New result API error : Can only use lower 16 bits for requestCode".
dependencies {
def activity_version = "1.2.0-beta01"
// Java language implementation
implementation "androidx.activity:activity:$activity_version"
// Kotlin
implementation "androidx.activity:activity-ktx:$activity_version"
def fragment_version = "1.3.0-beta02"
// Java language implementation
implementation "androidx.fragment:fragment:$fragment_version"
// Kotlin
implementation "androidx.fragment:fragment-ktx:$fragment_version"
// Testing Fragments in Isolation
debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
}
Now you just have to add this member variable of your activity. This use a predefined registry and generic contract.
public class MyActivity extends AppCompatActivity{
...
/**
* Activity callback API.
*/
// https://developer.android.com/training/basics/intents/result
private ActivityResultLauncher<Intent> mStartForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
switch (result.getResultCode()) {
case Activity.RESULT_OK:
Intent intent = result.getData();
// Handle the Intent
Toast.makeText(MyActivity.this, "Activity returned ok", Toast.LENGTH_SHORT).show();
break;
case Activity.RESULT_CANCELED:
Toast.makeText(MyActivity.this, "Activity canceled", Toast.LENGTH_SHORT).show();
break;
}
}
});
Before new API you had :
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MyActivity .this, EditActivity.class);
startActivityForResult(intent, Constants.INTENT_EDIT_REQUEST_CODE);
}
});
You may notice that the request code is now generated (and hold) by the Google framework.
Your code becomes:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MyActivity .this, EditActivity.class);
mStartForResult.launch(intent);
}
});
First you use startActivityForResult() with parameters in the first Activity and if you want to send data from the second Activity to first Activity then pass the value using Intent with the setResult() method and get that data inside the onActivityResult() method in the first Activity.
In your Main Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.takeCam).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent=new Intent(getApplicationContext(),TakePhotoActivity.class);
intent.putExtra("Mode","Take");
startActivity(intent);
}
});
findViewById(R.id.selectGal).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent=new Intent(getApplicationContext(),TakePhotoActivity.class);
intent.putExtra("Mode","Gallery");
startActivity(intent);
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
In Second Activity to Display
private static final int CAMERA_REQUEST = 1888;
private ImageView imageView;
private static final int MY_CAMERA_PERMISSION_CODE = 100;
private static final int PICK_PHOTO_FOR_AVATAR = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_take_photo);
imageView=findViewById(R.id.imageView);
if(getIntent().getStringExtra("Mode").equals("Gallery"))
{
pickImage();
}
else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.CAMERA}, MY_CAMERA_PERMISSION_CODE);
} else {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
}
}
}
public void pickImage() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, PICK_PHOTO_FOR_AVATAR);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == MY_CAMERA_PERMISSION_CODE)
{
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
else
{
Toast.makeText(this, "Camera Permission Denied..", Toast.LENGTH_LONG).show();
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
imageView.setImageBitmap(photo);
}
if (requestCode == PICK_PHOTO_FOR_AVATAR && resultCode == Activity.RESULT_OK) {
if (data == null) {
Log.d("ABC","No Such Image Selected");
return;
}
try {
Uri selectedData=data.getData();
Log.d("ABC","Image Pick-Up");
imageView.setImageURI(selectedData);
InputStream inputStream = getApplicationContext().getContentResolver().openInputStream(selectedData);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
Bitmap bmp=MediaStore.Images.Media.getBitmap(getContentResolver(),selectedData);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e){
}
}
}
You need to override Activity.onActivityResult():
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CODE_ONE) {
String a = data.getStringExtra("RESULT_CODE_ONE");
}
else if(resultCode == RESULT_CODE_TWO){
// b was clicked
}
else{
}
}

Unable to display result of camera activity in ImageView

Basically what I'm trying to do is create a simple app that uses the default camera app to take a picture, then I want to display that image in a new activity within an ImageView, but everything I've tried has resulted in
java.io.FileNotFoundException: /storage/emulated/0/imageToProcess.jpg: open failed: ENOENT (No such file or directory)
I've included the correct permissions (maybe even too many) in the manifest:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
and I'm also manually requesting permissions if need be in the main activity:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.CAMERA}, 1);
}
if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
if(checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
}
so I don't think the issue is with read/write permissions.
In my main activity's xml file, I've created a button with an onClick listener that calls the following method:
public void openCamera(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(Environment.getExternalStorageDirectory() + File.separator + "imageToProcess.jpg");
imgUri = Uri.fromFile(f);
intent.putExtra("imgUri", imgUri.toString());
startActivityForResult(intent, TAKE_PICTURE);
}
Here's the onActivityResult() method I defined to create a new intent and pass the uri to the new activity:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if(requestCode == TAKE_PICTURE && resultCode == Activity.RESULT_OK) {
Intent camResult = new Intent(this, ShowCameraResult.class);
camResult.putExtra("imgUri", imgUri.toString());
startActivity(camResult);
}
}
NOTE: imgUri and TAKE_PICTURE are defined at the top of the class as protected static final int TAKE_PICTURE = 1; and private Uri imgUri;
Lastly, here is my ShowCameraResult activity
public class ShowCameraResult extends AppCompatActivity {
private Bitmap mImageBitmap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_camera_result);
ImageView imageView = (ImageView)findViewById(R.id.imageView);
String filePath = getIntent().getStringExtra("imgUri");
Log.d("ShowCameraResult", "directory: " + filePath);
try {
mImageBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.parse(filePath));
imageView.setImageBitmap(mImageBitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
}
The Log.d method call above returns
ShowCameraResult: directory: file:///storage/emulated/0/imageToProcess.jpg
This leads me to believe that the image result from the camera isn't actually being saved into my imageToProcess.jpg file, but I could be very wrong as this is the first real android project I've worked on.
So my question is: Where did I go wrong?
Any help is greatly appreciated, thank you!
ITs returning a file, not a content resolver uri. Just decode the file with BitmapFactory.

Call method when intent closes

I am making a music player application, and I am trying to implement playlists. I have a file chooser in another intent, and I would like the ListView in the mainActivity to update when the file chooser intent closes. how can I call my UpdateListView method when it closes?
start intent:
Intent intent = new Intent(this, FileChooser.class);
startActivity(intent);
Closing intent
public void closeButton(View view){
finish();
}
Any help would be appreciated! thanks!
I assume you are using your own FileChoser class, not a standard Android one:
private static final int FileChooserRequestCode = 666;
Intent intent = new Intent(this, FileChooser.class);
startActivityForResult(intent, FileChooserRequestCode);
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == FillChooserRequestCode) {
if (resultCode == Activity.RESULT_OK) {
// ... file is chosen
String fileName = data.getStringExtra("FileName");
} else {
... dialog is closed
}
}
}
in FileChoser you do
Intent intent = new Intent();
intent.putStringExtra("FileName", fileName);
SetResult(Activity.RESULT_OK, intent);
finish();
and
SetResult(Activity.RESULT_CANCELED);
finish();
You can use startActivityForResult() please refer the link Getting Results From Activity
static final int FILE_CHOOSER_INTENT = 1; // The request code
...
private void chooseFile() {
Intent intent = new Intent(this, FileChooser.class);
startActivityForResult(intent, FILE_CHOOSER_INTENT);
}
Call setResult pass your result data as Intent. for details refer link SetResult function
Override this in your calling activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == FILE_CHOOSER_INTENT) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// The user picked a contact.
// The Intent's data Uri identifies which contact was selected.
// Do something with the contact here (bigger example below)
}
}
}

Android: cannot get values using .getStringExtra

I'll just go straight to the problem. In UploadNotesActivity.java....
First, I pick a .pdf file using intent
chooseNotesBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Create intent to Open Image applications like Gallery, Google Photos
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
// Start the Intent
startActivityForResult(intent, RESULT_LOAD_FILE);
}
});
and then, in `onActivityResult, I save the filePath of the picked file.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_FILE && resultCode == RESULT_OK && data != null) {
data.putExtra("filePath", data.getData().getPath());
choosenFile.setText(data.getStringExtra("filePath"));
} else {
Toast.makeText(this, "Error in choosing file",
Toast.LENGTH_LONG).show();
}
}
click Upload button to start upload the file
uploadNotesBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onUploadButtonClick();
}
});
the onUploadButtonClick()
private void onUploadButtonClick() {
final String serverUrlString = "http://XXXX/uploadNotes.php";
if (getIntent().getStringExtra("filePath").isEmpty()) {
Log.d(TAG, "filePath is null");
} else {
Log.d(TAG, getIntent().getStringExtra("filePath"));
}
final String fileToUploadPath = getIntent().getStringExtra("filePath");
final String paramNameString = "uploaded_file";
String fileName[] = fileToUploadPath.split("/");
final MultipartUploadRequest request =
new MultipartUploadRequest(this, UUID.randomUUID().toString(), serverUrlString);
request.addFileToUpload(fileToUploadPath, paramNameString,
fileName[fileName.length-1]+".pdf", ContentType.APPLICATION_OCTET_STREAM);
request.setNotificationConfig(R.drawable.ic_launcher,
getString(R.string.app_name),
getString(R.string.uploading),
getString(R.string.upload_success),
getString(R.string.upload_error),
false);
// if you comment the following line, the system default user-agent will be used
request.setCustomUserAgent("UploadServiceDemo/1.0");
// set the intent to perform when the user taps on the upload notification.
// currently tested only with intents that launches an activity
// if you comment this line, no action will be performed when the user taps
// on the notification
// request.setNotificationClickIntent(new Intent(this, MainActivity.class));
// set the maximum number of automatic upload retries on error
request.setMaxRetries(2);
try {
request.startUpload();
} catch (Exception exc) {
Toast toast = Toast.makeText(getApplicationContext(), "Malformed upload request. " + exc.getLocalizedMessage(), Toast.LENGTH_LONG);
toast.show();
}
}
But the problem is, it will throw null pointer exception, which I don't quite get the reason.
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.isEmpty()' on a null object reference
at com.fyp.mycyberlaw.Lecturer.UploadNotesActivity.onUploadButtonClick(UploadNotesActivity.java:73)
at com.fyp.mycyberlaw.Lecturer.UploadNotesActivity.access$100(UploadNotesActivity.java:19)
at com.fyp.mycyberlaw.Lecturer.UploadNotesActivity$2.onClick(UploadNotesActivity.java:53)
line 73: if (getIntent().getStringExtra("filePath").isEmpty())
line 19: public class UploadNotesActivity extends Activity
line 53: onUploadButtonClick();
Seems like the filePath in line 73 is empty and the way I save filePath into bundle (?) is incorrect. How to get the filePath from onActivityResult? Here's the .java class, just in case. Thank you in advance. Really need your help.
An Intentobject is used to pass params between activities. Ones you receives the file path you must to keep it in your activity.
Create a filePathvariable inside your activity, set it on onActivityResult and read it on onUploadButtonClick.
Notice that must save variable value during the onSaveInstanceState callback and restore it in onCreate because every time you turn your phone the activity is destroyed and recreated. Check this for more information: Recreating an Activity

ActivityNotFoundException when trying to start activity from an intent returned by Action.PICK_ACTIVITY

I am working on an application that associates "gestures" with activities (like Dolphin Browser do with urls). What I want to do is to allow the users to select an activity with Action.PICK_ACTIVITY :
Intent data = new Intent(Intent.ACTION_MAIN);
data.addCategory(Intent.CATEGORY_LAUNCHER);
Intent intent = new Intent(Intent.ACTION_PICK_ACTIVITY);
intent.putExtra(Intent.EXTRA_INTENT, data);
startActivityForResult(intent, PICK_ACTIVITY);
...
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_ACTIVITY && resultCode == RESULT_OK) {
Gesture gesture = new Gesture();
gesture.intent = data;
Intent intent = new Intent(this, GestureEditorActivity.class);
intent.putExtra("com.example.gesture.Gesture",gesture.toByteArray());
startActivity(intent);
}
}
And then, when the user draw the associated gesture, I start the activity :
Intent intent = GestureList.getInstance(getApplicationContext()).getIntentForGesture(gesture);//intent corresponds to data in onActivityResult method
if(intent != null)
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
else
Toast.makeText(this, R.string.unrecognized_gesture, Toast.LENGTH_LONG).show();
But I got an ActivityNotFoundException :
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.MAIN dat=#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;component=com.android.calculator2/.Calculator;end }
Here is my getIntentForGesture method :
public Intent getIntentForGesture(Gesture gesture)
{
float bestDist = Float.MAX_VALUE;
Gesture bestGesture = null;
for(Gesture g:this)
{
float dist = gesture.distance(g);
if(dist < bestDist)
{
bestDist = dist;
bestGesture = g;
}
}
if(bestGesture != null)
return bestGesture.intent;
else
return null;
}
Sorry for my broken English and thanks in advance for your answers
You have to add FLAG_ACTIVITY_NEW_TASK flag to your intent
Intent intent = GestureList.getInstance(getApplicationContext()).getIntentForGesture(gesture);//intent corresponds to data in onActivityResult method
if (intent != null) {
try {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} catch (ActivityNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
Toast.makeText(this, R.string.unrecognized_gesture, Toast.LENGTH_LONG).show();
}
The Calculator activity can't be found. Probably a problem in your manifest file, so you can try:
Option #1:
Check everything is well written. The error message states:
No Activity found to handle Intent { act=android.intent.action.MAIN dat=#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;component=**com.android.calculator2/.Calculator**;end }
That slash / may be the error.
OPTION #2:
The key in your case is that you are trying to open an activity from another package (in this particular gesture, the calculator), so you could try checking if you can launch the calculator app like this:
Intent calcInt = new Intent();
calcInt.setClassName("com.android.calculator2", "com.android.calculator2.Calculator");
startActivity(calcInt);
If the calculator doesn't launch with this simple code, then I would bet the device doesn't have the default calculator installed.
OPTION #3:
Post your Android Manifest file so we can check it.

Categories

Resources