How to prevent startActivity(intent) from creating 2 instances of activity? - java

I am using onesignal sdk to start activity on notification click:
public class MainActivity extends AppCompatActivity {
// adding webview variable
private WebView mWebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// OneSignal Initialization
OneSignal.startInit(this)
.inFocusDisplaying(OneSignal.OSInFocusDisplayOption.Notification)
.unsubscribeWhenNotificationsAreDisabled(true)
.init();
// initializing webview by matching with id in activity_main.xml
mWebView = (WebView) findViewById(R.id.activity_main_webview);
// Enable Javascript
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
// Setting up webview & webchrome client
mWebView.setWebViewClient(new WebViewClient());
mWebView.setWebChromeClient(new WebChromeClient());
// if url is passed via onesignal notification as via putextra, open that url else open homepage
String url = getIntent().getStringExtra("url");
if (url != null) {
mWebView.loadUrl(url);
} else {
mWebView.loadUrl("https://www.google.com");
}
OneSignal.startInit(this).setNotificationOpenedHandler(new OneSignal.NotificationOpenedHandler() {
#Override
public void notificationOpened(OSNotificationOpenResult result) {
JSONObject data = result.notification.payload.additionalData;
String launchURL;
if (data != null) {
launchURL = data.optString("launchURL", null);
// Log.d("Debug", "Launch URL: " + launchURL);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra("url", launchURL);
startActivity(intent);
} else {
Log.d("Debug", result.notification.payload.toJSONObject().toString());
}
}
}).init();
}
}
On clicking notification, Mainactivity of my app starts and then the activity initiated by code startActivity(intent) with extra data put using intent.putExtra("url", launchURL) starts, causing 2 instances.
I have tried adding FLAG_ACTIVITY_REORDER_TO_FRONT & FLAG_ACTIVITY_CLEAR_TOP flags but they cause only the initial main activity to start, the activity initiated by startActivity(intent) is not started with these flags.
How to make only 1 instance of activity to start (the one which is initiated by startActivity(intent)) on notification click?

Related

How to stop signInWithEmailAndPassword when another activity is started?

I am working on a login app using FirebaseAuth, I am implementing two separate Activities, one to work online and other for offline. There is third starter activity that tries to automatically login a user if his data is present on the SharedPreferences. When finish() is called on an activity signInWithEmailAndPassword won't stop.
when internet is not working and "Work Offline" button is clicked , it will lead the user to ActivityOffline. But when internet is restored while the user is on ActivityOffline , out of nowhere ActivityOnline will pop up because of signInWithEmailAndPassword on the starter activity which is already finished.
How can i stop signInWithEmailAndPassword when my Work Offline button is clicked?
public class Starter extends AppCompatActivity {
Button useOffline;
String email;
String password;
FirebaseAuth mAuth = FirebaseAuth.getInstance();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_starter);
Prefs prefs = new Prefs(this);
email = prefs.getStringEntry("email");
password = prefs.getStringEntry("password");
useOffline = findViewById(R.id.use_offline);
useOffline.setOnClickListener(v -> {
Intent intent = new Intent(Starter.this, OfflineActivity.class);
startActivity(intent);
finish();
});
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(() -> useOffline.setVisibility(View.VISIBLE), 5000);
if (email.equals("") || password.equals("")) {
Intent intent = new Intent(Starter.this, LoginActivity.class);
startActivity(intent);
finish();
} else {
mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
prefs.setStringEntry("UID", Objects.requireNonNull(FirebaseAuth.getInstance().getCurrentUser()).getUid());
Intent intent = new Intent(Starter.this, OnlineActivity.class);
startActivity(intent);
} else {
prefs.removeEntry("email");
prefs.removeEntry("password");
Intent intent = new Intent(Starter.this, LoginActivity.class);
startActivity(intent);
}
finish();
});
}
}
}
You can set a boolean flag to true when offline button press and check this flag before start online activity.

How to start new activity on nfc tag discovery?

I am writing a code which should return NFC tag value on the next activity ( page ) when NFC get detected during scan. What happens here is that when I launch the app for the first time it the first page shows for a fraction of a second and moves to second page directly ( activity ).
Here is the piece of code for the first activity ( which is just for asking user to tap to scan )
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
askPermissions();
mtxtViewNfcContent = (TextView) findViewById(R.id.text);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {
Toast.makeText(this, "No NFC", Toast.LENGTH_SHORT).show();
finish();
return;
}
else {
Intent in = new Intent(Main2Activity.this, MainActivity.class);
startActivity(in);
}
What I want is the the to show the first page at launch and when user tap to nfc scan, show the output on the next page ( MainActivity).
PS : I am new to android, please excuse with my codes.
what are you doing until now is to exit the app when the device doesnot support nfc or to start another activity when the device supports nfc.
you are actually not listening at all to any tag.
here you have two possibilities:
first : read an nfc tag in the first activity and then creat a new intent with and put the result of tag reading as extra bundel.
two : listen to tag existance in the first activity and then send the tag to second one and read it in the second activity.
I would prefer the first secinario.
on firstActivity:
public class MainActivity extends AppCompatActivity {
private PendingIntent pendingIntent;
private IntentFilter[] writeTagFilters;
private NfcAdapter nfcAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.AppTheme);
setContentView(R.layout.activity_main);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {
Toast.makeText(this, "No NFC", Toast.LENGTH_SHORT).show();
finish();
return;
}
setForeground();
}
private void setForeground() {
pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
writeTagFilters = new IntentFilter[]{tagDetected};
}
#Override
protected void onResume() {
super.onResume();
if (nfcAdapter != null) {
nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
}
processNfcTag(getIntent());
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
#Override
protected void onPause() {
super.onPause();
if (nfcAdapter != null) {
nfcAdapter.disableForegroundDispatch(this);
}
}
private void processNfcTag(Intent intent) {
//TODO: here you should to check if this intent is an NFC Intent, in case it is an nfc intent you could read it according of tag tech you have
// for example MifareUltralight.
MifareUltralight mfu = MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
try {
mfu.connect();
byte [] bytes = mfu.readPages(pageNumber);
mfu.close();
} catch (IOException e) {
e.printStackTrace();
}
// then you could get this bytes and send it to the other activity
}
please check this link to know how to send data between activities.
p.s: you should to check the code I have wrote it quickly.
You can use intent.putExtra (key,value) while calling the intent and use bundle on the result activity to fetch the variable data
use this while calling the intent
`Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("some_key", value);
intent.putExtra("some_other_key", "a value");
startActivity(intent);`
use this on result activity
`Bundle bundle = getIntent().getExtras();
int valueText = bundle.getInt("some_key");
String valueString = bundle.getString("some_other_key");
TextView textone =(TextView)findVeiwById(R.id.textone);
textone.setText(valueText);
TextView stringTextView = (TextView)FindViewById(R.id.stringTextView)
stringTextView.setText(valueString)`

NullPointerException on Intent between two Activities

I am trying to send an Intent value between two activities, though it appears, having read this, that in my second activity, the received intent is null; having encoutnered an NPE at runtime.
The intended functionality behind this is: 'the user scans a code in Activity A' -> 'a true value received and packed into an intent' -> 'Activity B opens, unpacks the intent and checks that the intent value is true' -> 'if true, the height of an ImageView in the activity is reduced by a set amount'.
I am therefore, not sure why my Intent is received as null in Activity B, as I would like this check to happen so that the height is updated when the activity opens?
Activity A:
//do the handling of the scanned code being true and display
//a dialog message on screen to confirm this
#Override
public void handleResult(Result result) {
final String myResult = result.getText();
Log.d("QRCodeScanner", result.getText());
Log.d("QRCodeScanner", result.getBarcodeFormat().toString());
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Activity Complete!");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
//the user has pressed the OK button
#Override
public void onClick(DialogInterface dialog, int which) {
scannerView.resumeCameraPreview(QRActivity.this);
//pack the intent and open our Activity B
Intent intent = new Intent(QRActivity.this, ActivityTank.class);
intent.putExtra("QRMethod", "readComplete");
startActivity(intent);
}
});
builder.setMessage(result.getText());
AlertDialog alert1 = builder.create();
alert1.show();
}
Activity B:
// in onCreate, I check that the bundled intent is true
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tank);
if (savedInstanceState == null) {
Bundle extras = getIntent().getExtras();
if (extras == null) {
//then the extras bundle is null, and nothing needs to be called here
}
else {
String method = extras.getString("QRmethod");
if (method.equals("readComplete")) {
updateTank();
}
}
}
}
//this is the method that is called when the intent check is true
public int tHeight = 350;
public void updateTank() {
ImageView tankH = (ImageView)findViewById(R.id.tankHeight);
ViewGroup.LayoutParams params = tankH.getLayoutParams();
params.height = tHeight - 35;
tankH.setLayoutParams(params);
}
In Activity B you have a typo while pulling QRMethod from the Intent extras. You are using QRmethod while you have set extras with 'QRMethod'.
You can use :
In first activity ( MainActivity page )
Intent i = new Intent(MainActivity.this,SecondActivity.class);
i.putExtra("QRmethod","readComplete" );
then you can get it from your second activity by :
In second activity ( SecondActivity page )
Intent intent = getIntent();
String YourtransferredData = intent.getExtras().getString("QRmethod");
You can get string value by using intent.getStringExtra() method like this in your second activity.
if (getIntent() != null){
getIntent().getStringExtra("QRmethod") //this s your "readComplete" value
}

android java endswith keeps crashing

I'm having a error with my code when i run it...All i want to do to make a webview in order to show a webpage in my app and to check the url if it ends with .m3u8 and then if it ends with .mp4 to open with the mxplayer(it's a media player app from the play store). I got the API of mxplayer from their site and added into my code but the problem is that when the link ends with .mp4 it crashes. Here's my code :
public class MainActivity extends AppCompatActivity {
private WebView myWebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myWebView = (WebView) findViewById(R.id.web1);
myWebView.getSettings().setLoadsImagesAutomatically(true);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
myWebView.getSettings().setDomStorageEnabled(true);
myWebView.loadUrl("url");
myWebView.setWebViewClient(new WebViewClient() {
// Api < 24
#Override
public boolean shouldOverrideUrlLoading(WebView myWebView, String url) {
if (url.endsWith(".mp4")) {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri videoUri = Uri.parse("http://techslides.com/demos/sample-videos/small.mp4");
intent.setDataAndType( videoUri, "application/x-mpegURL" );
intent.setPackage( "com.mxtech.videoplayer.pro" );
startActivity( intent );
return true;
} else {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
return true;
}
}
});
}
}

Receiving data from other Android apps only works once

I'm trying to develop a simple app, which receives text from other android Apps and then open a browser.
I have implemented it as described in the documentation here:
https://developer.android.com/training/sharing/receive.html
It works, but only once.
The first time a text is shared from an other App, the browser is opened correctly.
But the second time only my app is opened, but not the browser.
What could be the reason for this?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get the intent that started this activity
Intent intent = getIntent();
// Get the action of the intent
String action = intent.getAction();
// Get the type of intent (Text or Image)
String type = intent.getType();
// When Intent's action is 'ACTION+SEND' and Type is not null
if (Intent.ACTION_SEND.equals(action) && type != null) {
// When tyoe is 'text/plain'
if ("text/plain".equals(type)) {
handleSendText(intent); // Handle text being sent
}
}
}
private void handleSendText(Intent intent) {
// Get the text from intent
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) {
openBrowser(sharedText);
}
}
private void openBrowser(String text) {
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://example.com/api.php?text=" + text));
startActivity(browserIntent);
}
}
openBrowser method is called from the handleSendText method witch it is on the onCreate method , second time you open your app ( If you didnt press the back button ) your app is already created ! so the code will never execute.
Please check the life cycle of an android activity below
You may edit your code and call the openBrowser method on the onResume method or just make a button to call the method openBrowser Oncliking the button.

Categories

Resources