The argument “Intent data” from onActivityResult is null - java

I have an Activity A and a Fragment B.
In A I have this method:
private void installApp(String path){
Intent i = new Intent(Intent.ACTION_VIEW);
fileUri = Uri.fromFile(new File(path));
i.setDataAndType(fileUri, "application/vnd.android.package-archive");
i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
B.startActivityForResult(i, 101); //B has been initialized elsewhere
}
Which later calls this override in B:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
try{
super.onActivityResult(requestCode, resultCode, data);
//Can't d stuff with data because it's Null.
}
}catch (Exception e){
//Handles the exception
}
}
I've been searching for a while now and still can't figure it out why data is null. What did I miss?!
Thank you.

In Fragment B are you calling startActivityForResult(new Intent(getActivity(), ActivityA.class), REQUEST_CODE) ? (REQUEST_CODE being an int)
if so then:
In Activity A you are not starting an Activity for a result. you need to call: finish();
in Activity A rather than
startActivityForResult();
update your code to look like:
private void installApp(String path){
Intent i = new Intent(Intent.ACTION_VIEW);
fileUri = Uri.fromFile(new File(path));
i.setDataAndType(fileUri, "application/vnd.android.package-archive");
i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
setResult(RESULT_OK, i);
finish();
}

The documentation for ACTION_VIEW has "Output: nothing", which means that ACTION_VIEW implementations do not supply a result, and so using ACTION_VIEW with startActivityForResult() is pointless.

Related

Getting result from startActivityForResult inside BroadcastReciever, calling ACTION_INSTALL_PACKAGE Intent

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?

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)
}
}
}

Cannot refer non-final intent when using with onActivityResult

I was having some problem when trying to move to a new intent in onActivityResult. Here is the code:
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
IntentResult scanningResult = IntentIntegrator.parseActivityResult(
requestCode, resultCode, intent);
if (scanningResult != null) {
barcode = scanningResult.getContents();
new GetBookByBarcode(
new GetBookByBarcode.OnRoutineFinished() {
public void onFinish() {
String bookID = GetBookByBarcode.bookID;
if (bookID.equals("")) {
Toast toast = Toast.makeText(getApplicationContext(),
"Book not found, please try another barcode.",
Toast.LENGTH_SHORT);
toast.show();
} else {
intent = new Intent(context, ReserveBook.class);
intent.putExtra("BookID", bookID);
startActivity(intent);
BarcodeScan.this.finish();
}
}
}).execute();
} else {
Toast toast = Toast.makeText(getApplicationContext(),
"No scan data received!", Toast.LENGTH_SHORT);
toast.show();
}
}
}
Firstly, I will perform a barcode scan. When onActivityResult, I will execute the AsyncTask class. When the AsyncTask class onFinish, I then move to a new intent. However, I am getting error message:
Cannot refer to non-final variable intent inside inner class defined in different method.
at the intent inside the else statement. Any ideas? Thanks in advance.
Just declare a new Intent variable. You're creating a new Intent anyways, so there's no point trying to reference the non-final parameter from onActivityResult.
The reason you get this message from the compiler is because only final variables (and effectively final variables in Java 8) can be referenced inside an anonymous inner class like that.
Instead of doing
intent = new Intent(context, ReserveBook.class);
intent.putExtra("BookID", bookID);
startActivity(intent);
BarcodeScan.this.finish();
Try doing
Intent newIntent = new Intent(context, ReserveBook.class);
newIntent.putExtra("BookID", bookID);
startActivity(newIntent);
BarcodeScan.this.finish();
Because as of now, you are trying to access the parameter from onActivityResult which gives you the error.

how to handle a getIntent() method with java nullpointerexception

I have 2 activities in my application, Activity1 and Activity2.When the app launches Acitivity1 is the the one that is called.Clicking on a button in Activity1 should take you to Activity2.
In Acivity2,some data processing is done then i send back data to Activity1 using an intent like this:
Intent in=new Intent(getApplicationContext(), Activity1.class);
in.putExtra("data", data);
startActivity(in);
Then getting back to Activity1 i obtain the intent data:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity1);
String data =(getIntent().getExtras().getString("data"));
The problem here is that the first time the app launches it checks for the intent data and it does not exist so i get the nullpointerexception error.how can i make sure it checks for the intent data when Activity2 is the previous class?
You can check if the intent is existing using:
getIntent().hasExtra("data");
This will return you a boolean.
Also if oyu want to return some datas to the first activity, your should start the second one with startActivityForResult
if (extras != null) {
if (extras.containsKey("data")) {
boolean hasData = extras.getBoolean("data", false);
// TODO: Do something with the value of "data".
}
}
put a check over it
if(getIntent().getExtras()!=null){
String data =(getIntent().getExtras().getString("data"));
}
Follow the following steps
1: from your activity1's button click call as follow
Intent i = new Intent(this, SecondActivity.class);
startActivityForResult(i, 1);
2: In your Activity2 set the data which you want to return back to Activity1 as follow and if you don't want to return back don't set anything.
Intent returnIntent = new Intent();
returnIntent.putExtra("result",result);
setResult(RESULT_OK,returnIntent);
finish();
if you don't want to return data:
Intent returnIntent = new Intent();
setResult(RESULT_CANCELED, returnIntent);
finish();
3: now again in your Activity1 handle the return data as follow
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if(resultCode == RESULT_OK){
String result=data.getStringExtra("result");
}
if (resultCode == RESULT_CANCELED) {
//Write your code if there's no result
}
}
}
EDIT:
and if you strictly want to use your own method as in your question try this:
in your Activity1 you obtain the intent data as:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity1);
String data ="default value";
try{
data =(getIntent().getExtras().getString("data"));
}catch(Exception e){
}
}
use ActvityForResult.
replace these codes.
in ACTVITY1:
put this after onCreate:
#Override
protected void onActivityResult(int requestCode ,int resultCode ,Intent data ) {
super.onActivityResult(requestCode, resultCode, data);
String name =data.getStringExtra("data");
if(resultCode == RESULT_OK){
switch(requestCode){
case 2:
if(resultCode == RESULT_OK){
Toast.makeText(this, name, Toast.LENGTH_LONG).show();
}
}
}
in ACTIVITY2:
Intent intent=new Intent();
intent.putExtra("data",data);
setResult(2,intent);
finish();

Android Getting Results from another activity

I have a problem with my code. I want to pass a String from the SecondActivity to FirstActvity. Note that the FirstActivity is not visible but its still open. when the SecondActivity is finish it passes a String to the FirstActivity.
My problem here is that when the SecondActivity ended and goes to FirstActivity, the whole application closes.
FirstActivity to SecondActivity:
Intent intent = new Intent(MainActivity.this, FileChooser.class);
startActivityForResult(intent, 0);
SecondActivity to FirstActivity:
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("filePath", "/sdcard/path1");
setResult(0);
finish();
FirstActivity Result:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//TODO handle here.
Intent intent = getIntent();
this.filePath = intent.getExtras().getString("filePath");
}
What is wrong with the code?
When you set the result of your SecondActivity, you only set the result code. Instead of setResult(0) use setResult(0,intent)
Also, in your FirstActivity's onActivityResult get the extra from the data argument - this.filePath = data.getExtras().getString("filePath");
Try to use
data.getExtras().getString("filePath");
instead of
intent.getExtras().getString("filePath");`
Try with Bundle:
First Activity;
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), FIRSTACTIVITY.class);
Bundle bundle = new Bundle();
bundle.putString("filePath","/sdcard/path1");
intent.putExtras(bundle);
startActivity(intent);
}
Second Activity:
public void activity_value() {
Intent i = getIntent();
Bundle extras=i.getExtras();
if(extras !=null) {
value = extras.getString("filePath");
}
}
try this
example.It solves your problem.

Categories

Resources