#Override
public void onWindowFocusChanged(boolean hasFocus){
super.onWindowFocusChanged(hasFocus);
try{
if(!hasFocus && enableKioskMode){
Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(closeDialog);
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
am.moveTaskToFront(getTaskId(), ActivityManager.MOVE_TASK_WITH_HOME);
// sametime required to close opened notification area
Timer timer = new Timer();
timer.schedule(new TimerTask(){
public void run() {
Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(closeDialog);
}
}, 500);
}
}catch(Exception ex){
ex.printStackTrace();
}
}
private class CustomViewGroup extends ViewGroup {
public CustomViewGroup(Context context) {
super(context);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
}
private void addBlockingViews() {
try {
WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
//For Bottom View
WindowManager.LayoutParams bottomlocalLayoutParams = new WindowManager.LayoutParams();
bottomlocalLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
bottomlocalLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
bottomlocalLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
bottomlocalLayoutParams.height = (int) (50 * getResources().getDisplayMetrics().scaledDensity);
bottomlocalLayoutParams.format = PixelFormat.RGBX_8888;
bottomlocalLayoutParams.gravity = Gravity.BOTTOM;
bottomView = new CustomViewGroup(BaseActivity.this);
ViewGroup.LayoutParams layoutParams1 = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 50);
bottomView.setLayoutParams(layoutParams1);
manager.addView(bottomView, bottomlocalLayoutParams);
WindowManager.LayoutParams toplocalLayoutParams = new WindowManager.LayoutParams();
toplocalLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
toplocalLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");
int result = 0;
if (resId > 0) {
result = getResources().getDimensionPixelSize(resId);
} else {
// Use Fallback size:
result = 60; // 60px Fallback
}
//toplocalLayoutParams.height = result;
toplocalLayoutParams.height = (int) (50 * getResources().getDisplayMetrics().scaledDensity);
toplocalLayoutParams.gravity = Gravity.TOP;
toplocalLayoutParams.format = PixelFormat.TRANSPARENT;
topView = new CustomViewGroup(BaseActivity.this);
ViewGroup.LayoutParams layoutParams2 = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
25);
topView.setLayoutParams(layoutParams2);
manager.addView(topView, toplocalLayoutParams);
} catch (Exception e) {
e.printStackTrace();
}
}
My aim is to create a Kiosk app. I checked many codes for that like this and this. With their help I have achieved navigation bar hiding. Now I want to block user from dragging the notification bar down just like Surelock does. I've tried the common answers given in SO posts like here. But it does not work in my Redmi Note 5 Pro with Android Pie. Is there any other way to accomplish this?
In this solution notification bar is not blocked entirely but it gets closed after user opens it. You need a service that checks if the notification bar is open repeatedly. This service uses reflection to get needed method to close the notification bar after it gets opened so I think it wont work on android 9 devices(just checked it working fine with compilesdk 28 on a 7.1.1 device). you need to use this permission:
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
this is the code for the service:
public class CollapseService extends Service {
ScheduledExecutorService scheduler;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
MyRunnable runnable = new MyRunnable(this);
scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate
(runnable, 0, 100, TimeUnit.MILLISECONDS);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
private void collapseNow() {
Object statusBarService = getSystemService("statusbar");
Class<?> statusBarManager = null;
try {
statusBarManager = Class.forName("android.app.StatusBarManager");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method collapseStatusBar = null;
try {
collapseStatusBar = statusBarManager.getMethod("collapsePanels");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
collapseStatusBar.setAccessible(true);
try {
collapseStatusBar.invoke(statusBarService);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
#Override
public void onDestroy() {
super.onDestroy();
scheduler.shutdown();
}
static class MyRunnable implements Runnable{
CollapseService aService = null;
MyRunnable(CollapseService service){
WeakReference<CollapseService> weakReference = new WeakReference<>(service);
aService = weakReference.get();
}
#Override
public void run(){
if(aService != null) {
aService.collapseNow();
}
}
}
}
Weak reference is to remove the possibility of occurrence of memory leaks.
If your kiosk app is a device owner (as explained in one of your referenced examples) you can use DevicePolicyManager.setStatusBarDisabled() :
Disabling the status bar blocks notifications, quick settings and
other screen overlays that allow escaping from a single use device.
It is available since Android 6 (API 23), the status bar is still displayed (with the time, wifi level, bluetooth indicator, ...) but the notifications are not and you cannot expand it.
Related
After upgrade to target SDK 30, my AccessibilityService's Floating Window can't show on Android 12's System Setting UI. When enter the System Setting UI, Floating Window disappears. After quit the System Setting UI, Floating Window appears again.
I think it's a new limitation on android 12, before it's ok. Anyone have a workaround? as I really need to show some tips while doing in AccessibilityService. thank you.
addView:
if (mWindowManager != null) {
mWindowManager.addView(buildAnimWindow(), buildLayoutParams());
}
buildAnimWindow:
public AnimWindow buildAnimWindow() {
AnimWindow res;
LayoutInflater inflater = LayoutInflater.from(mContext);
res = (AnimWindow) inflater.inflate(R.layout.anim_window, null);
buildLayoutParams:
public WindowManager.LayoutParams buildLayoutParams() {
WindowManager.LayoutParams res;
res = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= 29) {
res.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
} else if (Build.VERSION.SDK_INT >= 26) {
res.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
res.type = WindowManager.LayoutParams.TYPE_PHONE;
}
This is a new safety precaution meant to prevent apps from tampering with or intercepting actions from the Settings app.
Unless you are using an Accessibility service, "abusing" a TYPE_ACCESSIBILITY_OVERLAY flag is not recommended. Per the TYPE_ACCESSIBILITY_OVERLAY documentation, albeit poorly written, such windows are only intended to allow an Accessibility service to intercept touch events without changing the views being introspected (examined).
Each user can opt in to displaying over Settings in the "Developer options" section of the Settings app (unlocked by tapping the "Build number" multiple times). Keep in mind that this is a blanket option, which allows any app with permission to display over other apps to also display over Settings.
ForegroundService did the trick, tested ok on android 12:
MyForegroundService:
public class MyForegroundService extends Service {
#Override
public void onCreate() {
super.onCreate();
startForegroundFullOs(NOTIFY_ID, buildNotify());
init();
}
private Context getContext() {
return MyForegroundService.this;
}
private void init() {
Logger.d(TAG, "BPFS::init");
mContext = getContext();
if (Build.VERSION.SDK_INT >= 29) {
if (MyService.getInstance() != null) {
mWindowContext = MyAccessibilityService.getInstance();
} else {
mWindowContext = getContext();
}
mWindowManager = (WindowManager) mWindowContext.getSystemService(Context.WINDOW_SERVICE);
} else {
mWindowContext = getContext();
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
}
}
#SuppressLint("InflateParams")
public MyAnimWindow buildMyAnimWindow() {
MyAnimWindow res;
LayoutInflater inflater = LayoutInflater.from(mWindowContext);
res = (MyAnimWindow) inflater.inflate(R.layout.anim_window, null);
Logger.d(TAG, "BPFS::buildMyAnimWindow, res = " + res);
return res;
}
public WindowManager.LayoutParams buildLayoutParams() {
WindowManager.LayoutParams res;
res = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= 29) {
res.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
} else if (Build.VERSION.SDK_INT >= 26) {
res.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
res.type = WindowManager.LayoutParams.TYPE_PHONE;
}
res.format = -3;
res.width = -1;
res.height = -1;
res.flags = 0;
res.flags |= 262144;
res.flags |= 1024;
res.flags |= 256;
res.flags |= 8;
res.flags |= Integer.MIN_VALUE;
res.gravity = 51;
res.x = 0;
res.y = 0;
return res;
}
public void showMyAnimWindow() {
try {
if (mWindowManager != null) {
mWindowManager.addView(buildMyAnimWindow(), buildLayoutParams());
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
MyAccessibilityService:
public class MyAccessibilityService extends AccessibilityService {
private static MyAccessibilityService sInstance;
public static MyAccessibilityService getInstance() {
return sInstance;
}
#Override
public void onCreate() {
super.onCreate();
sInstance = MyAccessibilityService.this;
}
I already done do to hide the status bar, but unfortunately I didn't found the way to display it back once its already hide. I did so many workaround but still not success, here and here.
Activity
WindowManager manager = ((WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to receive touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (50 * getResources()
.getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.TRANSPARENT;
customViewGroup view = new customViewGroup(this);
manager.addView(view, localLayoutParams);
customViewGroup class
class customViewGroup extends ViewGroup {
public customViewGroup(Context context) {
super(context);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
}
For Hiding Status Bar on 4.1 or Higher use
View decorView = getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
// Remember that you should never show the action bar if the
// status bar is hidden, so hide that too if necessary.
ActionBar actionBar = getActionBar();
actionBar.hide();
OR
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
To make Status Bar Visible
View decorView = getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_VISIBLE;
decorView.setSystemUiVisibility(uiOptions);
// Remember that you should never show the action bar if the
// status bar is hidden, so hide that too if necessary.
ActionBar actionBar = getActionBar();
actionBar.show();
OR
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
Refer Immersve View
android Exit from full screen mode
I think permanently disable the status bar is difficult. I am also working on the same concept and did lots of R&D and found that below code can be useful. if the user tries to expand the status bar then within a sec it will pull back it and it will work on oreo as well. I have tried on different OS.
public class BlockStatusBar {
Context context
// To keep track of activity's window focus
boolean currentFocus;
// To keep track of activity's foreground/background status
boolean isPaused;
public Handler collapseNotificationHandler;
Method collapseStatusBar = null;
public BlockStatusBar(Context context, boolean isPaused) {
this.context = context;
this.isPaused = isPaused;
collapseNow();
}
public void collapseNow() {
// Initialize 'collapseNotificationHandler'
if (collapseNotificationHandler == null) {
collapseNotificationHandler = new Handler();
}
// If window focus has been lost && activity is not in a paused state
// Its a valid check because showing of notification panel
// steals the focus from current activity's window, but does not
// 'pause' the activity
if (!currentFocus && !isPaused) {
Runnable myRunnable = new Runnable() {
public void run() {
// do something
try {
// Use reflection to trigger a method from 'StatusBarManager'
Object statusBarService = context.getSystemService("statusbar");
Class<?> statusBarManager = null;
try {
statusBarManager = Class.forName("android.app.StatusBarManager");
} catch (ClassNotFoundException e) {
Log.e(LOG_TAG, "" + e.getMessage());
}
try {
// Prior to API 17, the method to call is 'collapse()'
// API 17 onwards, the method to call is `collapsePanels()`
if (Build.VERSION.SDK_INT > 16) {
collapseStatusBar = statusBarManager.getMethod("collapsePanels");
} else {
collapseStatusBar = statusBarManager.getMethod("collapse");
}
} catch (NoSuchMethodException e) {
Log.e(LOG_TAG, "" + e.getMessage());
}
collapseStatusBar.setAccessible(true);
try {
collapseStatusBar.invoke(statusBarService);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
// Check if the window focus has been returned
// If it hasn'kioskthread been returned, post this Runnable again
// Currently, the delay is 100 ms. You can change this
// value to suit your needs.
if (!currentFocus && !isPaused) {
collapseNotificationHandler.postDelayed(this, 100L);
}
if (!currentFocus && isPaused) {
collapseNotificationHandler.removeCallbacksAndMessages(null);
}
} catch (Exception e) {
Log.e("MSG", "" + e.getMessage());
}
}
};
// Post a Runnable with some delay - currently set to 300 ms
collapseNotificationHandler.postDelayed(myRunnable, 1L);
}
}
}
I am using the below code to Play Audio file (.wav), but it plays the file with Echo(like playing two voice simultaneously) when activity is in Landscape mode.
public class Find_n_Display_StationActivity extends Activity
{
GPSTracker gps;
TextView txtvw,locNameTV;
boolean calculating_distance=false;
ArrayList<String>data=new ArrayList<String>();
ArrayList<String>latArray=new ArrayList<String>();
ArrayList<String>longArray=new ArrayList<String>();
MySQLiteHelper db = new MySQLiteHelper(this);
ImageView profileIV;
PendingIntent intent;
String reached_station="empty";
MediaPlayer mp;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.find_n__display__statn_activity);
txtvw=(TextView)findViewById(R.id.textView2);
locNameTV=(TextView)findViewById(R.id.textView1);
profileIV=(ImageView)findViewById(R.id.image11);
profileIV.setVisibility(View.GONE);
//Put in LANDSCAPE MODE...
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//Show FULL-SCREEN Activity
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//Calling/Starting Thread to Handl Uncaught Exeption
Thread.setDefaultUncaughtExceptionHandler(onRuntimeError);
//(((( This will retrieve DATA from service to this Activity ))))
gps = new GPSTracker(this);
LocalBroadcastManager.getInstance(this.getApplicationContext()).registerReceiver(
mMessageReceiver, new IntentFilter("GPSLocationUpdates"));
// mp=new MediaPlayer();
}//EOF Oncreate Method...
//(((( This Function is Called if App Crash, So, App is start Automatically after crash ))))
private Thread.UncaughtExceptionHandler onRuntimeError= new Thread.UncaughtExceptionHandler()
{
public void uncaughtException(Thread thread, Throwable ex)
{
Intent i=new Intent(getApplicationContext(),MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
};
// (((( This Class Get Data From Service class GPSTracker.class() ))))
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent) {
// Get extra data included in the Intent
String message = intent.getStringExtra("Status");
Bundle b = intent.getBundleExtra("Location");
Location lastKnownLoc = (Location) b.getParcelable("Location");
if (lastKnownLoc != null)
{
String s1=String.valueOf(lastKnownLoc.getLatitude());
String s2=String.valueOf(lastKnownLoc.getLongitude());
double current_lat=Double.parseDouble(s1);
double current_long=Double.parseDouble(s2);
txtvw.setText("____________________________\n\n\n"+current_lat+"\n"+current_long);
//showtoast("You have changed your Location");
if(calculating_distance==false)
{
calculating_distance=true;
FindDistance(current_lat,current_long);
}
Turn_On_Screen();
}
}};
private String stationPlayed="empty";
#SuppressWarnings("deprecation")
public void Turn_On_Screen()
{
WakeLock screenLock = ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
screenLock.acquire();
//later
//screenLock.release();
}
//(((( Find Distance Betwee All Points ))))))
public void FindDistance(double current_lat,double current_long)
{
Move_App_Back_to_ForeGround();
ArrayList<String>stationNameArray=new ArrayList<String>();
ArrayList<String>imageArray=new ArrayList<String>();
ArrayList<String>voiceArray=new ArrayList<String>();
imageArray=db.Get_ImageList();
voiceArray=db.Get_VoiceList();
stationNameArray=db.Get_StionNameAraay();
latArray=db.Get_LatAraay();
longArray=db.Get_LongAraay();
float smallest_dis=10000;
String next_station="";
boolean found_station=false;
for(int i=1;i<latArray.size();i++)
{
float lat1 = Float.parseFloat(latArray.get(i));
float long1 = Float.parseFloat(longArray.get(i));
float dis=FindDistance((float)current_lat,(float)current_long,lat1, long1);
if(dis<smallest_dis)
{
smallest_dis=dis;
next_station=stationNameArray.get(i);
}
if(dis<=50)
{
Set_Pic_n_Voice(imageArray.get(i),voiceArray.get(i),stationNameArray.get(i));
// showtoast("station-name="+ stationNameArray.get(i));
break;
}
}
locNameTV.setText("You are Heading towards Station="+next_station+"\n You are only "+smallest_dis+" Meter away...");
calculating_distance=false;
}
public void Set_Pic_n_Voice(String image,final String voice,final String station_name)
{
DisplayImage(image);
if(!reached_station.equalsIgnoreCase(station_name))
reached_station=""+station_name; //Don't play voice for same station just display pic always
//Wait for 4 seconds to play this voice
Runnable r = new Runnable()
{
public void run()
{
if(!stationPlayed.equalsIgnoreCase(station_name))
{
PlayVoice(voice);
stationPlayed=station_name;
}
}
};
android.os.Handler h = new android.os.Handler();
h.postDelayed(r, 5000);// */
}
//(((( Displaying Picture For the Station ))))
public void DisplayImage(String image)
{
profileIV.setVisibility(View.VISIBLE);
File imageFile = new File(Environment.getExternalStorageDirectory()+File.separator+"Bus_StationApp_Folder/Images",image);
if (imageFile.exists())
{
File imgFile = new File(imageFile.getAbsolutePath()); // path of your file
Picasso.with(this).load(Uri.fromFile(new File(imageFile.getAbsolutePath()))).into(profileIV);
/*
FileInputStream fis = null;
try {
fis = new FileInputStream(imgFile);
} catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
BitmapFactory.Options options = new BitmapFactory.Options();
//options.inSampleSize = 8;
//options.inPurgeable = true;
// options.inScaled = true;
Bitmap bm = BitmapFactory.decodeStream(fis, null,options);
profileIV.setImageBitmap(bm);//*/
}
else
profileIV.setImageResource(R.drawable.default_station_pic);
}
//(((( Playing Voice For The Station ))))))
public void PlayVoice(String voice)
{
calculating_distance=true;
// Play_Audio_File ob=new Play_Audio_File(this);
//ob.PlayVoice(voice);
File voiceFile = new File(Environment.getExternalStorageDirectory()+File.separator+"Bus_StationApp_Folder/Voices",voice);
if (voiceFile.exists())
{
if(!mp.isPlaying())
{
mp.reset();
try {
mp.setDataSource(voiceFile.getAbsolutePath());
mp.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
}
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
public void onCompletion(MediaPlayer mp)
{
calculating_distance=false;
}
});
}
else
{
//mp.reset();
mp= MediaPlayer.create(this, R.drawable.default_station_voice);
if(!mp.isPlaying())
{
mp.start();
}
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
public void onCompletion(MediaPlayer mp)
{
calculating_distance=false;
}
});
}
//*/
}
//((((( Find distance between two geolocation )))
public float FindDistance(float lat1, float lng1, float lat2, float lng2)
{
double earthRadius = 6371000; //meters
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLng/2) * Math.sin(dLng/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
float dist = (float) (earthRadius * c);
return dist;
}
//((( Move App To Screen from Background ))))
public void Move_App_Back_to_ForeGround()
{
boolean foregroud=false;
try
{
foregroud = new ForegroundCheckTask().execute(getApplicationContext()).get();
} catch (InterruptedException e)
{ e.printStackTrace();
}
catch (ExecutionException e)
{
e.printStackTrace();
}
if(!foregroud)
{
//Open Activity IF it is in Background...
Intent it = new Intent("intent.my.action");
it.setComponent(new ComponentName(this.getPackageName(), Find_n_Display_StationActivity.class.getName()));
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.getApplicationContext().startActivity(it);
}
}
class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> {
#Override
protected Boolean doInBackground(Context... params) {
final Context context = params[0].getApplicationContext();
return isAppOnForeground(context);
}
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
}
//SHOW-TOAST-MESSAGE
public void showtoast(String str)
{
Toast.makeText(getApplicationContext(), str, Toast.LENGTH_LONG).show();
}
public void OnBackPressed()
{
}
}//EOF Activity...
You are somehow calling the PlayVoice() method twice. The reason your inner if statement isn't preventing this is because you must be calling mp = new MediaPlayer(); before calling PlayVoice(), otherwise the first call to that method would result in a NullPointerException from the mp.isPlaying() call in the if condition. Since mp now points to a new MediaPlayer instance, isPlaying() returns false, and the if block executes again, even though the previous instance is still playing.
To prevent multiple instances of MediaPlayer playing concurrently, instantiate the MediaPlayer only once in the declaration line, remove the mp = new MediaPlayer(); line in PlayVoice() (and anywhere else you might have it), and un-comment the mp.reset(); call there.
The PlayVoice() method is being called twice because you're requesting an orientation change to landscape in the Activity's onCreate() method, and you're not handling configuration changes yourself. This is causing the Activity started in portrait mode to be destroyed and recreated, which means that onCreate() runs a second time, but the MediaPlayer started in the first Activity instance is still playing when a new one is created and started in the second instance.
You can prevent this from happening by forcing the Activity to launch in a landscape orientation from the start. You can do this by adding android:screenOrientation="landscape" to the <activity>'s tag in the manifest. You can also remove the setRequestedOrientation() call now, as it is no longer needed.
I've been able to hide the notification bar by going full screen, by using the code below
android:theme="#android:style/Theme.Holo.NoActionBar.Fullscreen"
or
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
But what I am trying to do is completely disable the status bar. I'm in what's known as a "kiosk mode" and I'd like to make sure that a user can not slide their finger down from the top bezel. Both of the solutions above work for hiding the notification bar, but it does not work for disabling it completely within the app.
Is this possible?
Instead of following links to other answers, here's what I did.
This solution does not disallow a user to "view" the status bar in it's 'preview' state if pulled down (even in a full screen app), but it DOES disallow a user from pulling the status bar down to it's full state to see settings, notifications, etc.
You must first add the permissions in your AndroidManifest.xml
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Then add another class (Java file) called customViewGroup.java and place this code in it:
import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewGroup;
public class customViewGroup extends ViewGroup {
public customViewGroup(Context context) {
super(context);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("customViewGroup", "**********Intercepted");
return true;
}
}
After you have both of those set up, you can then add this into your main onCreate()
WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (50 * getResources().getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.TRANSPARENT;
customViewGroup view = new customViewGroup(this);
manager.addView(view, localLayoutParams);
This solution disables the ability to pull the status bar down always, until your app is closed. You'll have to remove this action on pause if you don't want to close your app every time.
Credit goes to #Abhimaan Madhav from This Answer
I think permanently disable the status bar is difficult. I am also working on the same concept and did lots of R&D and found that below code can be useful. if the user tries to expand the status bar then within a sec it will pull back it and it will work on oreo as well. I have tried on different OS.
public class BlockStatusBar {
Context context;
// To keep track of activity's window focus
boolean currentFocus;
// To keep track of activity's foreground/background status
boolean isPaused;
public Handler collapseNotificationHandler;
Method collapseStatusBar = null;
public BlockStatusBar(Context context, boolean isPaused) {
this.context = context;
this.isPaused = isPaused;
collapseNow();
}
public void collapseNow() {
// Initialize 'collapseNotificationHandler'
if (collapseNotificationHandler == null) {
collapseNotificationHandler = new Handler();
}
// If window focus has been lost && activity is not in a paused state
// Its a valid check because showing of notification panel
// steals the focus from current activity's window, but does not
// 'pause' the activity
if (!currentFocus && !isPaused) {
Runnable myRunnable = new Runnable() {
public void run() {
// do something
try {
// Use reflection to trigger a method from 'StatusBarManager'
Object statusBarService = context.getSystemService("statusbar");
Class<?> statusBarManager = null;
try {
statusBarManager = Class.forName("android.app.StatusBarManager");
} catch (ClassNotFoundException e) {
Log.e(LOG_TAG, "" + e.getMessage());
}
try {
// Prior to API 17, the method to call is 'collapse()'
// API 17 onwards, the method to call is `collapsePanels()`
if (Build.VERSION.SDK_INT > 16) {
collapseStatusBar = statusBarManager.getMethod("collapsePanels");
} else {
collapseStatusBar = statusBarManager.getMethod("collapse");
}
} catch (NoSuchMethodException e) {
Log.e(LOG_TAG, "" + e.getMessage());
}
collapseStatusBar.setAccessible(true);
try {
collapseStatusBar.invoke(statusBarService);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
// Check if the window focus has been returned
// If it hasn'kioskthread been returned, post this Runnable again
// Currently, the delay is 100 ms. You can change this
// value to suit your needs.
if (!currentFocus && !isPaused) {
collapseNotificationHandler.postDelayed(this, 100L);
}
if (!currentFocus && isPaused) {
collapseNotificationHandler.removeCallbacksAndMessages(null);
}
} catch (Exception e) {
Log.e("MSG", "" + e.getMessage());
}
}
};
// Post a Runnable with some delay - currently set to 300 ms
collapseNotificationHandler.postDelayed(myRunnable, 1L);
}
}
}
I had written certain code such that my android app should go to airplane mode and come back to connected mode with the network for around some time until i close the application forcibly.
Its working with the code I had written but the problem is that the screen or display is not showing the flight symbol.
When I go to settings, I can see that the code is enabling and disabling the air plane mode properly.
Can any one please give me a solution for this.
My code is as follows
public class Airplane_ModeActivity extends Activity implements Runnable{
private static final int SLEEP_TIME_VALUE = 10000;
private static Context context;
private static ContentResolver contentResolver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context = getApplicationContext();
contentResolver = context.getContentResolver();
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", false);
sendBroadcast(intent);
Runnable runnable = new Airplane_ModeActivity();
Thread thread = new Thread(runnable);
thread.start();
}
public void run(){
while(true) {
while(0==Settings.System.getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, 0) ) {
Settings.System.putInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, 1);
try {
Thread.sleep(SLEEP_TIME_VALUE);
}
catch (InterruptedException ie) {
}
}
try {
Thread.sleep(SLEEP_TIME_VALUE);
}
catch (InterruptedException ie) {
}
while(1==Settings.System.getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, 1) ) {
Settings.System.putInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, 0);
try {
Thread.sleep(SLEEP_TIME_VALUE);
}
catch (InterruptedException ie) {
}
}
try {
Thread.sleep(SLEEP_TIME_VALUE);
}
catch (InterruptedException ie) {
}
}
}
}
boolean isEnabled = Settings.System.getInt(thisActivity.getContentResolver(),Settings.System.AIRPLANE_MODE_ON, 0) == 1;
Settings.System.putInt(thisActivity.getContentResolver(),Settings.System.AIRPLANE_MODE_ON,isEnabled ? 0 : 1);
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", !isEnabled);
sendBroadcast(intent);
Check with this one., I think this will help you ..