RE: Move back to App after launching another App
and Launching Intent from service causes crash
I now have the terminal launching correctly from my service, however my next step is to, after the service has launched the terminal intent to relaunch the apps main activity.
I am doing this using:
public void backtoEmplayer(){
Intent intenti = new Intent(MainService.this,MainActivity.class);
intenti.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intenti.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intenti);
}
So that it will simply bring forward the main activity which should still be running (As the only two things ever launched on this device will be my app and the terminal).
However when I run the above code I get the following error:
E/AndroidRuntime (1859): FATAL EXCEPTION: Thread-931
E/AndroidRuntime (1859): android.util.AndroidRuntimeException: Calling startActvitiy() from outside of an Activity context requires the FLAT_ACTIVITY_NEW_TASK flas. Is this really what you want?
E/AndroidRuntime (1859): at android.app.ContextImpl.startActivity(ContextImpl.java:864)
E/AndroidRuntime (1859): at android.content.ContentWrapper.startActivity(ContextWrapper.java 276)
E/AndroidRuntime (1859): at packagename.MainService.backtoEmplayer(MainService.java:187)
What I do not understand is that fact that I am using the FLAT_ACTIVITY_NEW_TASK flag but it still does not work.
My complete service class now looks like:
public class MainService extends Service {
boolean copied = false;
private String mHandle;
private static final int REQUEST_WINDOW_HANDLE = 1;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
}
#Override
public void onDestroy() {
}
#Override
public void onStart(Intent intent, int startId) {
Thread usbUpdateThread = new Thread() {
public void run() {
while (true) {
while (!copied) {
try {
Thread.sleep(180000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
runCommand("chmod -R 777 /media/cdrom/");
copied = false;
}
}
};
Thread InternetThread = new Thread() {
public void run() {
while (true){
try {
Thread.sleep(3600000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
runCommand("php update.php");
}
}
};
Thread CheckThread = new Thread() {
public void run() {
while (true) {
try {
Thread.sleep(300000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
runCommand("sh check.sh");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
backtoEmplayer();
}
}
};
InternetThread.start();
CheckThread.start();
usbUpdateThread.start();
}
public boolean runCommand(String command) {
Intent intent = new Intent("jackpal.androidterm.RUN_SCRIPT");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.putExtra("jackpal.androidterm.iInitialCommand", command);
intent.putExtra("jackpal.androidterm.window_handle", MainActivity.mHandle);
startActivity(intent);
return true;
}
public void backtoEmplayer(){
Intent intenti = new Intent(MainService.this,MainActivity.class);
intenti.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intenti.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intenti);
}
}
Remove
intenti.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
from your code.
Related
I implemented a vpnservice that block all packets,it works in most app and blocks fine but it doesn't work in some apps . why is that ?
myVpnService is like below.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Start a new session by creating a new thread.
mThread = new Thread(new Runnable() {
#Override
public void run() {
try {
builder = new Builder();
mInterface = builder.setSession("ClashDisconnect")
.addAddress("192.168.0.1", 32)
.addDnsServer("8.8.8.4")
.addRoute("0.0.0.0", 1).establish();
Log.d("after establish", "yes");
DatagramChannel tunnel = DatagramChannel.open();
// Connect to the server, localhost is used for demonstration only.
tunnel.connect(new InetSocketAddress("127.0.0.1", 8081));
//d. Protect this socket, so package send by it will not be feedback to the vpn service.
protect(tunnel.socket());
//e. Use a loop to pass packets.
while (true) {
Thread.sleep(100);
}
} catch (Exception e) {
// Catch any exception
Log.d("Exception", "in Catch");
e.printStackTrace();
} finally {
try {
if (mInterface != null) {
mInterface.close();
mInterface = null;
}
} catch (Exception e) {
}
}
}
}, "MyVpnRunnable");
//start the service
mThread.start();
onDestroy();
}
};
return START_STICKY;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
if (mThread != null) {
mThread.interrupt();
mThread = null;
builder = null;
}
super.onDestroy();
}
and another weird problem is it work in some phone but not all phone .
I want to when user click on button, start a Service.
When the service starts .
I want to show 5 times text
The delay time is 3 seconds .
show_toast1-------delay 3secounds ,
show_toast2-------delay 3secounds,
show_toast3-------delay 3secounds,.......
but when click on button Delay only occurs once!
and other show_toast is displayed without delay
java code :
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
for(int i=0;i<4;i++)
{
try {
Toast.makeText(getBaseContext(), "show_toast"+i, Toast.LENGTH_LONG).show();
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
return START_STICKY;
}
Use Handler instead if Thread.sleep() , Try the code below will work for you.
public Handler handler; //global
int i = 0; //global
final Handler handler = new Handler();
runable = new Runnable() {
#Override
public void run() {
try{
//do your code here
if(i < 4){
Toast.makeText(MainActivity.this, "show_toast"+i, Toast.LENGTH_LONG).show();
i = i + 1;
//also call the same runnable
handler.postDelayed(this, 5000);
}
else{
handler.removeCallbacks(runable);
}
}
catch (Exception e) {
// TODO: handle exception
}
}
};
handler.postDelayed(runable, 5000);
In IntentService i am using ThreadPoolExecutor poolSize 8 and maxPoolSize 10. When ever Service is started it will effect on UI. In runTask() method i am add tasks to thread pool.
private ThreadPoolExecutor threadPool = null;
private final LinkedBlockingQueue<Runnable> threadsQueue =
new LinkedBlockingQueue<Runnable>();
private Collection<Future<?>> futures = new LinkedList<Future<?>>();
public MyService(String name) {
super(name);
threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize, keepAliveTime,
TimeUnit.SECONDS, threadsQueue);
}
public void runTask(Runnable task) {
futures.add(threadPool.submit(task));
}
/**
* When ever we call this method it will hold the main thread untill the tasks
* in thread pool are completed.
*/
public void waitForThreadPool() {
for (Future<?> future : futures) {
try {
future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
I suggest creating a separate thread in a Service (Service runs in UI thread) which will wait for the executors to finish. This is how I done it
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// check what you have to here
// ...
if (state == State.IDLE) {
state = State.IN_PROGRESS;
new Thread()
{
#Override
public void run()
{
performAndWait();
stopSelf();
}
}.start();
}
}
private void performAndWait() {
//add tasks to ExecutorService
for (String key : this.data.keySet()) {
final Job pending = new Job(this.context, key, this.data.get(key));
try {
this.service.submit(pending);
} catch (RejectedExecutionException e) {
// all rejected stuff go here for the next attempt when all finishes
this.rejected.add(pending);
}
}
// wait
service.shutdown();
try {
service.awaitTermination(3600, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
I have a Service which runs a thread. This thread runs a timertask, this timertask now has to run another thread.
My Service class looks like this:
Timer pTimer;
int Time = 1;
int samplerate=100;
int sampleSize=((Time*1000)/samplerate);
Accelerometer_Thread Ac_Thread;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
pTimer = new Timer();
Ac_Thread = new Accelerometer_Thread();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// TODO Auto-generated method stub
//super.onStart(intent, startId);
Ac_Thread.start();
return START_STICKY;
}
public class Accelerometer_Thread extends Thread{
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
pTimer.scheduleAtFixedRate(task,0, samplerate);
}
}
/* The Timertask which is to be executed at a periodic interval of "samplerate" */
TimerTask task = new TimerTask() {
#Override
public void run() {
// TODO Auto-generated method stub
String Ack = null;
try {
Ack = Post.PostToWebService("Hello");
} catch (Exception e) {
// TODO Auto-generated catch block
}
if (Ack.contentEquals("1")) {
//Do SOmething
}
else
Log.d("Error", "NotSent To Webservice");
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
};
The Post.PostToWebService which starts the Thread looks like this:
public static String ReceivedAcknowledgement=null;
public static String buffer;
public static String PostToWebService(String Payload){
CallPost cp = new CallPost();
buffer = Payload;
ReceivedAcknowledgement="STRT";
try {
cp.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cp.start();
while(ReceivedAcknowledgement=="STRT")
{
try
{
Thread.sleep(10);
}catch(Exception ex)
{
}
}
if(ReceivedAcknowledgement != "STRT")
return ReceivedAcknowledgement;
else
return null;
}
The CallPost looks like this:
public class CallPost extends Thread{
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
Post.ReceivedAcknowledgement = ParseXML(in);
}
private String ParseXML(InputStream i){
//Parse
}
}
I'm getting an error in my Service class at the line Post.PostToWebService("Hello") where the error says:
java.lang.RuntimeException: Can't create handler inside thread that
has not called Looper.prepare()
I've tried understanding about loopers and handlers but I'm not able to get it.
I am facing a grave problem. Inside a service I am opening Wifi connection and closing it after my task completes. Since, a service exits at any point i face a problem wherein the connection opens and remains open.
Is there a way i can handle this as i am using START_STICKY or i will have to handle it programmatically only?
EDIT : Can i share my intent information across couple of receivers (BroadcastReceiver). For example, I will write another receiver for action android.net.wifi.wifi_state_changed and my existing receiver is for android.intent.action.PHONE_STATE.
IF that can be achieved i can do something about it.
EDIT2 : My code is as follows:
public class CallReceiver extends BroadcastReceiver {
private static final String LOG_TAG = "CallReceiver";
private static final String CALL_ACTION = "android.intent.action.PHONE_STATE";
#Override
public void onReceive(Context context, Intent callIntent)
{
Log.d(LOG_TAG, "----------------Inside onReceive of CallReceiver----------------");
if (callIntent.getAction().equals(CALL_ACTION))
{
try
{
Intent myIntent = new Intent(context, MyService.class);
context.startService(myIntent);
}
catch (Exception e)
{
e.printStackTrace();
Log.d(LOG_TAG,"----------------Exception occured while starting service----------------");
}
}
}
}
public class MyService extends Service {
private Context context;
private static final String LOG_TAG = "MyService";
private Thread thread = null;
public MyService()
{
super();
Log.d(LOG_TAG, "----------------Inside Email Service constructor----------------");
}
public int onStartCommand(Intent myIntent, int flags, int startId)
{
Log.d(LOG_TAG, "----------------Email Service Command Started----------------");
try
{
context = getApplicationContext();
if(thread == null || !thread.isAlive())
{
thread = new Thread(new MyRunnable("Email Sender", myIntent));
thread.start();
}
}
catch (Exception e)
{
e.printStackTrace();
Log.d(LOG_TAG,
"----------------Exception occured in Email Service onStartCommand----------------");
}
return START_REDELIVER_INTENT;
}
class MyRunnable implements Runnable {
String name;
Intent myIntent;
public MyRunnable(String name, Intent myIntent) {
this.name = name;
this.myIntent = myIntent;
}
#Override
public void run()
{
try
{
doStuff(emailIntent);
}
catch (NumberFormatException e)
{
e.printStackTrace();
Log.d(LOG_TAG, e.getMessage());
}
catch (InterruptedException e)
{
e.printStackTrace();
Log.d(LOG_TAG, e.getMessage());
}
catch (Exception e)
{
e.printStackTrace();
Log.d(LOG_TAG, e.getMessage());
}
finally
{
stopSelf();
}
}
}
private void doStuff(Intent emailIntent) throws InterruptedException, Exception
{
if (context != null)
{
boolean isWifiConnection = false;
try
{
// Check if WiFi connection is available ,if yes try opening it;
// Attempt to open WiFi connection
isWifiConnection = Utility.isEnableWifiSuccessful(getApplicationContext());
Log.d(LOG_TAG, "----------------Wifi conn enabled = " + isWifiConnection
+ "----------------");
if (isWifiConnection)
{
// Do more stuff
}
}
catch (Exception e)
{
e.printStackTrace();
throw e;
}
finally
{
// Code never reaches here !! Somehow, the service stops and by
// the time the service stops,
// WiFi has been enabled
try
{
if (isWifiConnection)
{
Utility.isDisableWifiSuccessful(getApplicationContext());
}
}
catch (Exception e)
{
e.printStackTrace();
Log.d(LOG_TAG,
"----------------Error occured while closing network connections----------------");
}
}
}
else
{
Log.d(LOG_TAG, "----------------Context is null----------------");
}
}
#Override
public IBinder onBind(Intent intent)
{
// TODO Auto-generated method stub
return null;
}
}
Now, if i have another receiver as NetworkReceiver
public class NetworkReceiver extends BroadcastReceiver {
private static final String ACTION = "android.net.wifi.WIFI_STATE_CHANGED";
private static final String LOG_TAG = "NetworkReceiver";
#Override
public void onReceive(Context context, Intent networkIntent)
{
if(networkIntent.getAction().equals(ACTION))
{
Log.d(LOG_TAG, "----------------Inside Network Receiver----------------");
//Do something which will keep track who has opened the WiFi connection
}
}
}
then can myIntent and networkIntent share information and can MySerivce read that information.
Any help would be really grateful.
Service exits when the memory is too low, since you are already using START_STICKY, the service will be restarted once the memory resources are available. I beleive you might need to check if the connection is opened and you are done with the task, then you have stop the service by using stopSelf().
Hope this helps.
Thanks,
Ramesh