Background Information: I want to create a child lock application. Therefore I need to disable all the keys (including the Home key) when the user is in the application. I basically want a similar application to this one.
Problem: If I have set another application as the default home launcher (ie. in HTC the Home Sense UI, or something similar in Samsung phones) and then set my application as the default home launcher, then pressing the Home key takes me back to the home screen (even though I set my application as the default home launcher!). Now, if I don't set any other applications as the default home launcher, only my own application, then there is no problem, and when I'm inside my application and press the Home key I stay in the application.
Why is it that when I set a default home application before I set my application as the default, the Home key doesn't work (ie. leaves my app)? But when I only set my application as the default, the Home key works (ie. stays in my app).
Below is sample code for my test application:
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testspinner"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.testspinner.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java:
public class MainActivity extends Activity {
private PackageManager pm;
#Override
protected void onCreate(Bundle savedInstanceState) {
this.pm = getPackageManager();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public boolean isHomeActivity() {
final IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
List<IntentFilter> filters = new ArrayList<IntentFilter>();
filters.add(filter);
final String myPackageName = getPackageName();
List<ComponentName> activities = new ArrayList<ComponentName>();
final PackageManager packageManager = (PackageManager) getPackageManager();
packageManager.getPreferredActivities(filters, activities, null);
for (ComponentName activity : activities) {
if (myPackageName.equals(activity.getPackageName())) {
return true;
}
}
return false;
}
protected void onResume() {
super.onResume();
if (!isHomeActivity()) {
Intent localIntent = new Intent(Intent.ACTION_MAIN);
localIntent.addCategory(Intent.CATEGORY_HOME);
localIntent.setComponent(new ComponentName("android",
"com.android.internal.app.ResolverActivity"));
startActivity(localIntent);
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK: {
finish();
}
}
return false;
}
}
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
You can check this project on Github: https://github.com/Neamar/Summon
It's an alternative Home Application that works properly.
I don't see what can create your described behavior. It's perhaps a device-specific issue.
Did you try a reboot after setting up your app?
If you are using certain versions of Android, you actually have to clear the defaults of the app that has been set as default. I was having the same problem as you. Then I checked out the app called Home Switcher for Froyo on the app market. In that app, if a default has been set, Home Switcher brings up the default launcher's app settings screen and tells the user to select the button "clear defaults." This is the only way that I know of.
So in your app, you have to check a few different things.
If no default launcher is set, set yours (like you said above that it works already)
If a default is set, launch its app settings, prompt user to select "clear defaults", then have them press the home button and select your app
I hope this helps, I don't know if I am the best person to ask for code examples as my app is still a little buggy, but I can point you to some stack overflow answers:
https://stackoverflow.com/a/4772481/1817139
https://stackoverflow.com/a/10344985/1817139
Good luck, email me if you're stuck (lus u s_v [i] r at yahoo) - ignore brackets and spaces
Related
I need to add a shortcut for my app on the home screen (programmatically).
I know that the app store do this by default, but for start, the app won't be on the google app store.
I searched a lot, and found basically the same lines of code over and over, and it doesn't seem to work for me.
the code I used:
in the manifest:
<activity android:name=".MainScreenActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
in the onCreate method I called the function that does the following:
private boolean createShortcut()
{
//create shortcut intent
Intent shortcutIntent = new Intent(getApplicationContext(),MainScreenActivity.class);
shortcutIntent.setAction(Intent.ACTION_MAIN);
//create intent to add and define the shortcut
Intent addingIntent = new Intent();
addingIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT,shortcutIntent);
addingIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME,"SenseGuard");
addingIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,Intent.ShortcutIconResource.fromContext(getApplicationContext(),R.drawable.peak_detection_icon));
addingIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
getApplicationContext().sendBroadcast(addingIntent);
}
I tried switching "getApplicationContext()" to "this".
I tried with an actual tablet and on an emulator but I can't get it to work.
Do like This:
Step 1:
Update your manifest.xml :
<uses-permission
android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
Step 2:
in your MainActivity.java create addShortcut() method and in it`s block put this code :
private void addShourcut(){
Intent shortCutIntent = new Intent(getApplicationContext() ,MainActivity.class);
shortCutIntent.setAction(Intent.ACTION_MAIN);
Intent addIntent = new Intent();
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT , shortCutIntent);
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME , "Convertor");
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE ,
Intent.ShortcutIconResource.fromContext(getApplicationContext() , R.mipmap.ic_launcher));
addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
addIntent.putExtra("duplicate" , false);
getApplicationContext().sendBroadcast(addIntent);
}
Step3:
set onClickListener for your view that be create shortcut :
img_pin = (ImageView) findViewById(R.id.img_pin);
img_pin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addShourcut();
Toast.makeText(MainActivity.this, "shortcut created !", Toast.LENGTH_SHORT).show();
}
});
This is worked for me ...
happy codinngggg...:)
That code isn't guaranteed to work. That broadcast is also sent by ShortcutManagerCompat (which you should probably be using instead of manually sending the broadcast).
However, there are two problems with this.
Your default launcher isn't guaranteed to listen for this broadcast. Nova Launcher, for example, has this behavior disabled by default. Other launchers might not even listen for that action at all.
On Android Oreo (26) and above, this won't work how you expect it to (read the comments on the method I linked for more details).
You can use this logic still and hope that it works for some of your users, but keep in mind that many default launchers no longer even have app drawers, so adding a shortcut could give your users duplicate icons. Also, I know that, at least for me, I have my home screen organized how I want, and if I install an app, it would be really annoying for it to add itself to my home screen.
If you are using the default AOSP launcher (or a close fork), however, and it isn't working, make sure you add this to your manifest:
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
I try to add welcome tutorial for users that install application for the first time. That activity need to be declare as Main in Manifest (or I miss something?). But if I choose any other activity else than main one (which is actual app), app shortcuts (Android 7.1) doesn't work anymore. It's interesting however that shortcuts are still available at custom launchers (Apex, Nova). Any idea?
(almost all) Google apps has welcome tutorial as well as launcher shortcuts. I can't get it how they did it?
A welcome tutorial does not have to be an activity. It could be some other sort of presentation (e.g., a fragment).
A welcome tutorial, even if it is another activity, does not have to be the launcher activity. The launcher activity could detect that it is the first run and started the tutorial activity.
Thank you for the answers CommonWare! Your statements helps me to find answer. So, I want to start an app which shows Splash screen, then Welcome tutorial. Also, app need working shortcuts on main screen as well as only one launcher icon. So, first, I declare Splash screen as main in Manifest.xml:
<activity
android:name=".SplashActivity"
android:noHistory="true"
android:theme="#style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:resource="#xml/shortcuts" />
</activity>
Then, Welcome (tutorial) activity:
<activity
android:name=".IntroActivity.WelcomeActivity"/>
After that, in SplashActivity.class checking first launch:
public static final String FIRST_APP_LAUNCH = "com.ips.test";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (isFirstAppLaunch()) {
setFirstAppLaunch(false);
startActivity(new Intent(this, WelcomeActivity.class));
} else {
startActivity(new Intent(this, MainActivity.class));
}
finish();
}
private boolean isFirstAppLaunch() {
SharedPreferences preferences = this.getPreferences(Context.MODE_PRIVATE);
return preferences.getBoolean(FIRST_APP_LAUNCH, true);
}
private void setFirstAppLaunch(boolean value) {
SharedPreferences preferences = this.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(FIRST_APP_LAUNCH, value);
editor.apply();
}
}
Final result is as I wanted: app launch with Splash screen, then it runs Welcome tutorial. Next start will trigger Splash screen which will continue to main activity (app itself). When user click on shortcut in main screen it will get shortcuts, and in Launcher it will have just one application shortcut.
I'm working on a fairly simple app. It has 3 activities, each with a picture as a background with a different TextView displaying different strings over the image. My environment: Mac OSX Yosemite, Eclipse Juno version 23.
Here's my issue. I'll make a change, such as altering the text from "123456789" to "012345678", and run the app. Logcat and the console display no errors and says the app has been installed. I open the app on either an emulator or device, and it shows the changes I've made ONLY on the first time I run the app. If I make any additional changes, they will not be picked up. I have tried deleting and re-creating my emulator, and it doesn't work. I've tried setting it to wipe previous data, but that doesn't work either. Eclipse will only recognize my Samsung Galaxy S3 ONCE. Then when I try to run it again on the phone, it doesn't come up as a device. If I restart my computer completely, it will all work again, but only once. It's driving me insane and I've spent 2 days trying to resolve it. I haven't found any information online that I haven't tried. It's as if restarting my computer wipes some data so that it'll work again, but where?
Here's my main activity.
package com.autotec.nfcdemo;
public class MainActivity extends ActionBarActivity {
private NfcAdapter nfcAdapter;
private ListView listView;
private IsoDepAdapter isoDepAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onResume() {
super.onResume();
null);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
// int id = item.getItemId();
// if (id == R.id.action_settings) {
// return true;
// }
// return super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case R.id.action_joe:
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
return true;
case R.id.action_jane:
intent = new Intent(this, Jane.class);
startActivity(intent);
return true;
case R.id.action_john:
intent = new Intent(this, John.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
Here's the MainActivity XML file.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:adjustViewBounds="true"
android:background="#drawable/card"
android:gravity="center_horizontal"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="85dp"
android:layout_marginTop="250dp"
android:textColor="#000000"
android:textSize="18sp"
android:textStyle="bold"
android:typeface="serif"
android:text="123456789" />
</LinearLayout>
And here's my AndroidManifest.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.autotec.nfcdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc.hce" />
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="#drawable/aa_launcher_icon_high"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Jane"
android:label="#string/title_activity_jane" >
</activity>
<activity
android:name=".John"
android:label="#string/title_activity_john" >
</activity>
</application>
</manifest>
One thing to check is your console logs... sometimes it will say something along the lines of : Warning: Activity not started, its current task has been brought to the front" If this happens your new changes are not necessarily loaded...This is usually caused by unfinished dialogs or toasts etc.
The way to avoid this is close the app manually on the simulator before loading new versions.
If this doesn't resolve your issue, be sure to clean your project before building and loading. (in eclipse, project->clean...)
Good luck!
Can you show us "where" did you make that change?! As far as I can see, the TextView has the value "123456789" and that would be the one that it's going to show every time you open the app.
You can make this on the onCreate:
TextView yourTextView = (TextView) findViewById(R.id.textView1)
yourTextView.setText("012345678");
and that would change the text from "123456789" to "012345678" every time you open the app.
You can simply change the android:text="123456789" to "012345678" if you don't need the 1st value.
Other way to keep your new value is by using a "SharedPreferences" and save that data (key value) on internal storage of your app and get it later or every time you open the app.
I'm creating a sample lock screen application in this i must override the home button, after i researched in both google and stackoverflow i got the result, it's complicated to do it. Here i mention what i did in my app,
Created a service with broadcast-receiver to show my lock screen when the screen goes to off. - working fine.
To override the home, menu, back and search buttons i used the following code,
hope we can override the home button when the application only becomes a launcher so in my manifest.xml i added this code.
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
</intent-filter>
Also in my Activity i used this code too
#Override
public void onAttachedToWindow() {
// TODO Auto-generated method stub
this.getWindow().setType(
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
| WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
super.onAttachedToWindow();
}
So far in my sample application i successfully completed the above to. Now my problem is,
When i unlock the screen then go to any apps, then i click the Device home button, My Lock screen will appear. i tired to disable this but i don't know how can i exactly do this, for this i used some code like below,
/* This should come from a preference that let's the user select an activity that can handle the HOME intent */
String packageName = "com.android.launcher";
String packageClass = "com.android.launcher2.Launcher";
Intent home_intent = new Intent(Intent.ACTION_MAIN);
home_intent.addCategory(Intent.CATEGORY_HOME);
home_intent.setComponent(new ComponentName(packageName, packageClass));
home_intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
/* Here you should catch the exception when the launcher has been uninstalled, and let the user save themselves by opening the Market or an app list or something. Users sometimes use root apps to uninstall the system launcher, so your fake launcher is all that is left. Might as well give the poor user a hand. */
startActivity(home_intent);
No code will help me, my exact need is once i unlock the screen i need to show the default home screen until the screen goes to screen off. is any idea to handle this issue? Thanks in Advance.
Try this solution,
Create a static variable flag which is set to true when you receive the broadcast for when screen goes to off
now in your activity check if the flag is true
#Override
public void onAttachedToWindow() {
if(MyService.Flag == true){
//Continue with your code ...
//....
}else{
finish();
}
}
or do it on onCreate which ever is suitable for you
Once your screen is unlocked then
//Disable the flag
MyService.Flag = false;
Now when your user clicks the Home button the activity is called and check again the flag again and if its false then call the finish() to close the activity
I've developed and app that is a slide show of pictures which each play a sound when you tap them. It's like a picture book for ages 2-4.
The problem is, since android won't let you capture a home button press and essentially disable it, when parents give the phone to their child to play with unattended (brave parent), the child can inadvertenly exit the app and then make calls or otherwise tweak the phone.
There are two other apps that currently have a psuedo fix for this issue. The apps are Toddler Lock and ToddlePhone. I've tried contacting the developers of these apps for some guidance but they haven't been willing to disclose anything, which if fine, but does anyone here have any suggestions?
It looks like both of those other apps are acting like a home screen replacement app. When you enable the "childproof mode" on those apps the user is prompted to chose and app for the action and the choices are "Launcher, LauncherPro, etc." plus the toddler app. You then have to make the toddler app the default and voila, the phone is "locked" and can only be "unlocked" using a key combination or touching the four corners of the screen, etc. when you "unlock" the phone. your normal home screen app default restored. You don't even have to make the toddler app the default the next time you enable the "childproof mode".
I have read that these two apps have problems with Samsung phones and they can cause an an infinite crash-and-restart-loop that requires a factory reset to fix. Obviously this is not the ideal solution to the problem but it looks like the only one availiable at this point.
Does anyone have any ideas on how to implement a "childproof mode"?
I needed to have toddler lock in a new app, and did not want to use a launcher.
Here is what I did, you can see the app at https://play.google.com/store/apps/details?id=com.justforkids.animalsounds
When lock is activated, start a service, and stop it when lock is deactivated
The service checks the top running app, and if it is not my activity, the service launches my activity
There was still an issue that when the user clicks "home", it takes about 6 seconds before my activity is launched again. I assume this is a security feature in Android but not sure. To bypass this, when the service detects that another app is visible, it adds a top view (as an alert window) that covers the home screen for the few seconds it takes the app to re-launch.
For step 3, here are more details:
Create the overlay layout, for example file locked_overlay.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#d0000000"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_horizontal"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:text="#string/app_name"
android:textColor="#fff"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Locked mode is on"
android:textColor="#fff"
android:textSize="18sp" />
</LinearLayout>
</FrameLayout>
In your service to show or hide the overlay use:
private View lockedOverlay = null;
private void hideLockedOverlay() {
if (lockedOverlay != null) {
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
windowManager.removeView(lockedOverlay);
lockedOverlay = null;
}
}
private void showLockedOverlay() {
if (lockedOverlay != null) {
return;
}
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams viewLayoutParams = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT);
viewLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
LayoutInflater inflater = LayoutInflater.from(this);
lockedOverlay = inflater.inflate(R.layout.locked_overlay, null);
windowManager.addView(lockedOverlay, viewLayoutParams);
}
You will need the permission
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
I think you're right regarding the home screen replacement. Toddler Lock I know doesn't override the home button, because (at least on my LG GW620) while in Toddle Lock holding the home button brings up the ALT-TAB type menu - which then tends to crash the phone.
There is a home screen replacement app available, with source code, on the android dev site:
http://developer.android.com/resources/samples/Home/index.html
EDIT: also, ADW.Launcher:
http://code.google.com/p/adw-launcher-android/
Add in to your Main Activity
#Override
public void onAttachedToWindow()
{
this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
super.onAttachedToWindow();
}
And Override Key down event
#Override
public boolean onKeyDown(int iKeyCode, KeyEvent event)
{
if(iKeyCode == KeyEvent.KEYCODE_BACK || iKeyCode == KeyEvent.KEYCODE_HOME)
{
return true;
}
}
Edit:
This works in all older version of android. But will not work in ICS and jelly bean and will give you crash in app
For versions 4.0 and above you can avoid Android security restrictions and set your app as a launcher. Add this to your manifest file:
<uses-permission android:name="android.permission.GET_TASKS" />
<activity
android:launchMode="singleInstance"
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</activity>
I replaced the Default Home launcher using the following code:
Intent selector = new Intent("android.intent.action.MAIN");
selector.addCategory("android.intent.category.HOME");
selector.setComponent(new ComponentName("android","com.android.internal.app.ResolverActivity"));
startActivity(selector);