Going back to previous activity using ActionBar navigation - java

In my app, I model Lists of items. In MainActivity, I see ListView containing Lists. I can click on each list to see its items (DisplayListActivity). On DisplayListActivity, I have button in the ActionBar to display the list properties. This launches the third activity (EditListPropertiesActivity).
Main
| ^
V |
DisplayListActivity (listId is passed with Intent, default=1)
| ^
V |
EditListPropertiesActivity (listId is passed with Intent, default=1)
The problem appears, when I select List id=2 on the MainActivity, and then I select the properties button on the DisplayListActivity. Once I am done with the EditListPropertiesActivity, i click '<' (back) on the ActionBar: .
I return to the DisplayListActivity, but instead of going back to the list id=2, I see the list with id=1 (which is default).
How to pass the ListId back form EditListPropertiesActivity to the DisplayListActivity?
startActivityForResult and return the id - would work, but I see it ugly
use the SharedPreferences and store sth like lastVisitedList - ugly
store the lastVisitedList information in the db - even uglier
What is the usual solution for that problem?
Code snippets below.
MainActivity
public class MainActivity extends Activity {
...
listView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
MetaList mlist = (MetaList) listView.getItemAtPosition(i);
final Intent intent;
intent = new Intent(getApplicationContext(), DisplayListActivity.class);
intent.putExtra(META_LIST_SELECTED, mlist.getId());
startActivity(intent);
}
}
);
...
DisplayListActivity
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.single_list);
intent = getIntent();
metaListId = intent.getLongExtra(MainActivity.META_LIST_SELECTED, 1); //read the data or take 1 as default
...
//start the third activity
final Intent intent;
intent = new Intent(getApplicationContext(), EditListPropertiesActivity.class);
intent.putExtra(META_LIST_SELECTED, metaListId);
startActivity(intent);
....
EditListPropertiesActivity
public class EditListPropertiesActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_list_parameters);
getActionBar().setDisplayHomeAsUpEnabled(true); //this enables the '<' (back) button
intent = getIntent();
metaListId = intent.getLongExtra(DisplayMetaListActivity.META_LIST_SELECTED, 1);
...
Manifest
<application>
<activity
android:name=".MainActivity">
</activity>
<activity
android:name="com.example.tutorial1.DisplayListActivity"
android:parentActivityName="com.example.tutorial1.MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.tutorial1.MainActivity" />
</activity>
<activity
android:name="com.example.tutorial1.EditListPropertiesActivity"
android:parentActivityName="com.example.tutorial1.DisplayListActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.tutorial1.DisplayListActivity" />
</activity>
</application>

try this to finish an activity
Intent intent = new Intent();
intent.putExtra(EXTRA, value);
setResult(RESULT_OK, output);
finish();
and this for getting the result in the previous activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(data.getExtras().containsKey(EXTRA)){
// do stuff with data from finished activity
String bla = data.getStringExtra(EXTRA)
}
}
EDIT: read comments! need to use startActivityForResult

try to call finish(); that you should call on destroy of the current activity and display the previous activity.

I have found the solution that works. I post it here, because it is cleaner (in my opinion) and different than the other proposed. I set the launch mode of the second activity to singleTask in the manifest file: android:launchMode="singleTask"
...
<activity
android:name="com.example.tutorial1.DisplayListActivity"
android:label="Meta List"
android:parentActivityName="com.example.tutorial1.MainActivity"
android:launchMode="singleTask">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.tutorial1.MainActivity" />
</activity>
...
If there is a better solution for the stated problem, I am open for discussion :)

Related

How to Update activity when open notification

I am working on notification and I have a problem. I have an activity already open when I click on notification I don't want to open it again just update the current activity.
if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
Intent pushNotification = null;
if (NotificationType != 0 && NotificationType != 2 && NotificationType != 5 && NotificationType != 26) {
pushNotification = new Intent(getApplication(), SplashScreen.class);
pushNotification.putExtra("NotificationType", NotificationType);
pushNotification.putExtra("ReferenceID", ReferenceID);
pushNotification.putExtra("NotificationID", ReferenceID);
pushNotification.putExtra("isread", ReferenceID);
showNotificationMessage(getApplicationContext(), title, message, time, pushNotification);
} else if (NotificationType == 0 || NotificationType == 2 || NotificationType == 5 || NotificationType == 26) {
showNotificationMessageWithNoAction(getApplicationContext(), title, message, title, null);
}
}
can Anyone tell me how I update the activity when I click on notification?
You just need to declare the launchMode to the singleTask to make ensure that multiple same screens not will open.
There are four launch modes for activity. They are:
1. Standard
2. SingleTop
3. SingleTask
4. SingleInstance
Please refer this link Click here
<activity android:name="YOUR_SPLASH_ACTIVITY"
android:launchMode="singleTask"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
And in the Java code , you just override the onNewIntent method , to refresh activity,
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
/**
* HERE YOU JUST REFRESH , YOUR ACTIVITY
*/
}
I don't know if this is what you need but you can do this
finish();
startActivity(getIntent());
Let me know what you really need.
EDIT:
If you need to keep your activity state intact, you can do this
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("MyString", "Welcome back to Android");
}
This will save your activity state
And then you retrieve UI state like this
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
String myString = savedInstanceState.getString("MyString");
}
Best way is to make use of the onNewIntent(Intent) method of your Activity.
You can use the Intent parameter of this method to get your Intent Extras, because getIntent() will give the Intent that started the Activity in the first place.
public class MainActivity extends Activity {
public void onCreate(Bundle SavedInstanceState) {
//Initial loading
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if(intent.getStringExtra("methodName").equals("myMethod")) {
//Update the existing screen
}
}
}

Button to return to Intent

I have the following sequence of pages:
-MainActivity
-Intent(Select a picture)
-DadosActivity
In MainActivity I have a button to open an intent for the user to select a photo, with the following code:
Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
if (i.resolveActivity(MainActivity.this.getPackageManager()) != null) {
startActivityForResult(i, SELECAO_GALERIA);
}
In this intent, the user will select a photo and after this is sent that selected item to another page, through this code:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == MainActivity.this.RESULT_OK) {
Bitmap image = null;
try {
switch (requestCode) {
case SELECAO_CAMERA:
image = (Bitmap) data.getExtras().get("data");
break;
case SELECAO_GALERIA:
Uri localImagemSelecionada = data.getData();
image = MediaStore.Images.Media.getBitmap(MainActivity.this.getContentResolver(), localImagemSelecionada);
break;
}
if (image != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 70, baos);
byte[] dadosImagem = baos.toByteArray();
Intent i = new Intent(MainActivity.this, DadosPostagemActivity.class);
i.putExtra("fotoEscolhida", dadosImagem);
startActivity(i);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
In the last activity, DadosActivity, the user can make some changes in the image, but my problem is when pressing the button on the back of the device and / or the toolbar, with the following code:
toolbar = (Toolbar) findViewById(R.id.tb_dados);
toolbar.setTitle("Adicione uma descrição");
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
According to what I did on AndroidManifest
<activity
android:name=".activity.DadosPostagemActivity"
android:parentActivityName=".activity.MainActivity" />
Activity is returning to MainActivity, but I wanted to press it to return to the intent and to choose the image again.
Does anyone have any suggestions on how to do this, so that instead of returning to MainActivity, back to the intent so that he can choose the image again?
Use the Codes Below..
In Manifest.xml file change code of AddPhoto Activity and AddDescription Activity like this-
This is for Addphoto Activity
<activity android:name=".AddPhoto"
android:label="Add Photo"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>
This is for AddDescription Activity
<activity android:name=".AddDescription"
android:label="Add Description"
android:parentActivityName=".AddPhoto">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".AddPhoto" />
</activity>
Now your problems are solved. In the code we declared that Addphoto activity is a child of Main Activity and AddDescription Activity is a child of Addphoto Acitivity.
Change the AddPhoto and AddDescription with your own activity name.
Best of Luck.
Thanks for everyone, I I found the solution was to just overwrite the method onBackPressed

Speed up the startup of BroadcastReceiver at reboot

I've an app where the user can call custom lock screen to lock his/her mobile, that is an activity called LockScreen.class.
One this screen is loaded, i.e. the deviced is locked, a SharedPreferences called IsLocked is assigned to be true.
once the user do what he need with tthe lock screen this islocked became false, and the mobile is back to normal.
Every hing is working fine as expected.
The problem is, if for some reason the mobile had been rebooted while the lock screen is active, it is not running back upon a reboot.
So, I created a BootReciever as below, this works fine BUT after having the reboot process completed, and the user can do many things before it is loaded, my question is how can I make it loaded faster? so that the mobile screen is locked again with the custom activity before giving the chance for the user to do anything with the mobile?
public class BootReciever extends BroadcastReceiver
{
SharedPreferences mPrefs;
final String IsLockedPref = "IsLocked";
#Override
public void onReceive(Context context, Intent intent) {
mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
Boolean islocked = mPrefs.getBoolean(IsLockedPref, false);
Intent i;
if (islocked)
i = new Intent(context, LockScreen.class);
else
i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
part of the manifiest file is:
<receiver android:name=".BootReciever"
android:enabled="true"
android:exported="true">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
UPDATE
I tried to get use of this by granting Device Admin by adding the below, but nothing improved:
In the main Activity:
private static final int ADMIN_INTENT = 15;
private static final String description = "Some Description About Your Admin";
private DevicePolicyManager mDevicePolicyManager;
private ComponentName mComponentName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDevicePolicyManager = (DevicePolicyManager)getSystemService(
this.DEVICE_POLICY_SERVICE);
mComponentName = new ComponentName(this, AdminReceiver.class);
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mComponentName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,description);
startActivityForResult(intent, ADMIN_INTENT);
.
.
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ADMIN_INTENT) {
if (resultCode == RESULT_OK) {
Toast.makeText(getApplicationContext(), "Registered As Admin", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(), "Failed to register as Admin", Toast.LENGTH_SHORT).show();
}
}
}
and created empty receiver to extend the DeviceAdminReceiver as:
public class AdminReceiver extends DeviceAdminReceiver {
}
and added the below to the manifiest:
<receiver
android:name="AdminReceiver"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="#xml/admin"/>
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
One thing you can do from your side is to set a priority to your intent-filter. From documentation
It controls the order in which broadcast receivers are executed to receive broadcast messages. Those with higher priority values are called before those with lower values.
<intent-filter
android:priority="100">
...
</intent-filter>
The value must be an integer, such as "100". Higher numbers have a higher priority. The default value is 0. The value must be greater than -1000 and less than 1000.

Run Activity only by first start

I just want to start a activity on the first run. So after I run it once it should never open again.This Activity is added with
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
so this Activity starts first.
I have a variable which helps me to decide if this Activity started for the first time or not (Im saving it with SharedPreferences which is called sem_first_time).When it is 0 then its the first time if not then this Activity have to finish and start another one.
Here's my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences data = getSharedPreferences("datas",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = data.edit();
first_start = data.getInt("fstart", 0);
if (first_start == 1)
{
finish();
Intent start = new Intent(this, Main.class);
startActivity(start);
}
setContentView(R.layout.first_start);
I got a Button which sets first_start to 1
public void create (View view)
{
SharedPreferences data = getSharedPreferences("datas",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = data.edit();
first_start = 1;
editor.putInt("fstart", first_start);
...
}
But when I start this App once It is showing this Activity again ... What is wrong ?
It is happening because this is the Launcher activity and you are finishing the activity before launching the other activity . It should be like
if (first_start == 1)
{
Intent start = new Intent(this, Main.class);
startActivity(start);
finish();
}

Intent issue (display new form) Android

Ok I've been looking around for hours. I've tried just about everything and I'm not sure what is going on but I'm getting the issue where it can't find the activity. The activity is in my manifest file. I've tried with .ActivityName and com...ActivityName. I've saved, I've cleaned, I've closed/opened eclipse. It just can't seem to find it. Here's code, maybe I'm missing something?
Manifest file:
<activity android:name=".Activity2"></activity>
Listener in MainActivity:
View.OnClickListener test = new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,Activity2.class);
startActivity(intent);
}
};
Activity2:
public class Activity2 extends Activity {
ImageButton btnTest;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TODO Auto-generated method stub
btnTest= (ImageButton)findViewById(R.id.btnDepressed);
btnTest.setOnClickListener(GoTest);
}
...etc.
I've read so many articles on this from here and other sites. I've watched videos.. I simply don't see what I'm doing wrong. The activity is defined in the manifest, I've tried the intent with the above code, as well as with:
new Intent("com.blah.blah.Activity2");
Neither is working. Any ideas?
try this
<activity android:name=".Activity2"
android:label="#string/app_name">
<intent-filter>
<action android:name="com.blah.blah.Activity2" />
</intent-filter>
</activity>
from activity code you have to do some thing like this
Intent intent = new Intent();
intent.setAction("com.blah.blah.Activity2");
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivity(intent);`
Check your package com.blah.blah for Activity2.
Inside your AndroidManifest.xml you should define your package as:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.blah.blah"
...
And define your activity as:
<activity
android:name="com.blah.blah.Activity2">
</activity>
OR
<activity
android:name=".Activity2">
</activity>

Categories