I know there are few similar threads out there I have tried them all, none of them seem to work for me. I'm trying capture Screenshots in Android but unfortunately It keeps crashing and giving me this error. In AndroidMaifest.xml the name is in red as if it's not getting recognised.
public class ScreenshotAction extends SinglePressAction {
private static Context mContext;
private String mScreenshotLabel;
private Drawable mScreenshotIcon;
private static final Object mScreenshotLock = new Object();
private static ServiceConnection mScreenshotConnection = null;
public ScreenshotAction(){
super();
}
public ScreenshotAction(Context context, String screenshotLabel, Drawable screenshotIcon) {
super(context);
mContext = context;
mScreenshotLabel = screenshotLabel;
mScreenshotIcon = screenshotIcon;
}
#Override
protected void setupLabel(TextView labelView) {
labelView.setText(mScreenshotLabel);
}
#Override
protected void setupIcon(ImageView icon) {
icon.setImageDrawable(mScreenshotIcon);
}
#Override
protected void onPress() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
takeScreenshot(handler);
Toast.makeText(mContext, "screenshot ok", Toast.LENGTH_LONG).show();
}
}, 1000);
}
public static void takeScreenshot(final Handler mHandler) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
return;
}
ComponentName cn = new ComponentName("com.android.systemui",
"com.android.systemui.screenshot.TakeScreenshotService");
Intent intent = new Intent();
intent.setComponent(cn);
ServiceConnection conn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != this) {
return;
}
Messenger messenger = new Messenger(service);
Message msg = Message.obtain(null, 1);
final ServiceConnection myConn = this;
Handler h = new Handler(mHandler.getLooper()) {
#Override
public void handleMessage(Message msg) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection == myConn) {
mContext.unbindService(mScreenshotConnection);
mScreenshotConnection = null;
mHandler.removeCallbacks(mScreenshotTimeout);
}
}
}
};
msg.replyTo = new Messenger(h);
msg.arg1 = msg.arg2 = 0;
try {
messenger.send(msg);
} catch (RemoteException e) {
}
}
}
#Override
public void onServiceDisconnected(ComponentName name) {}
};
if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
mScreenshotConnection = conn;
mHandler.postDelayed(mScreenshotTimeout, 10000);
}
}
}
private static final Runnable mScreenshotTimeout = new Runnable() {
#Override
public void run() {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
mContext.unbindService(mScreenshotConnection);
mScreenshotConnection = null;
}
}
}
};
}
Error:-
E/AndroidRuntime: FATAL EXCEPTION: main
Process: ......, PID: 6022
java.lang.SecurityException: Not allowed to bind to service Intent { cmp=com.android.systemui/.screenshot.TakeScreenshotService }
at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1595)
at android.app.ContextImpl.bindService(ContextImpl.java:1559)
at android.content.ContextWrapper.bindService(ContextWrapper.java:517)
AndroidMaifest.xml
This name is in red which tells me that it doesn't recognise it.
<service android:name=".screenshot.TakeScreenshotService"
android:process=":screenshot"
android:exported="true" />
I'm trying capture Screenshots in Android
Use the media projection APIs on Android 5.0+.
It keeps crashing and giving me this error
You do not have rights to bind to that service. You do not even know if that service exists on any given device.
This name is in red which tells me that it doesn't recognise it.
That is because you did not write that service.
Related
I am trying to understand the difference bwtettn STICKY and NOT_STICKY intent of a service in onStartCommand().
I created the MainActivity and the Service shown in the code below. I expected when I press the button mBtnStopApp, the onDestroy() wil be called and then
I should receive this log ** Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS NOT RUNNING ++++++++")); **
because onStartCommand() returns NOT_STICKY intnet which means, when the App is killed, the service should also be stopped
but that never happens.
what happens is, when i press the button mBtnStopApp, the App is finished but i receive the following log:
** Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS RUNNING ++++++++")); **
please let me know why the service is still running despite it returns START_NOT_STICKY and the App was killed
MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private TextView mTv = null;
private Button mBtnStartStickyService = null;
private Button mBtnStartNonStickyService = null;
private Button mBtnStopApp = null;
private Button mBtnStopNonStickyService = null;
private Button mBtnStopStickyService = null;
private ServicesUtils mServiceUtils = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.w(TAG, SubTag.bullet("#onCreate"));
this.mServiceUtils = new ServicesUtils(this);
this.mBtnStartNonStickyService = (Button) findViewById(R.id.btnNonStickyService);
this.mBtnStartStickyService = (Button) findViewById(R.id.btnStickyService);
this.mBtnStopApp = (Button) findViewById(R.id.btnStopApp);
this.mBtnStopNonStickyService = (Button) findViewById(R.id.btnStopNonStickyService);
this.mBtnStopStickyService = (Button) findViewById(R.id.btnStopStickyService);
this.mTv = (TextView) findViewById(R.id.tv);
this.mBtnStartNonStickyService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ComponentName componentName = startService(setRunningStateForService(NonStickyService.class, "start"));
Log.i(TAG, "#mBtnStartNonStickyService: componentName: " + componentName);
}
});
this.mBtnStopNonStickyService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ComponentName componentName = startService(setRunningStateForService(NonStickyService.class, "stop"));
Log.i(TAG, "#mBtnStopNonStickyService: componentName: " + componentName);
}
});
this.mBtnStopApp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
private Intent setRunningStateForService(Class<NonStickyService> serviceClass, String state) {
Log.w(TAG, SubTag.bullet("#setRunningStateForService"));
Intent intent = new Intent(this, serviceClass);
intent.putExtra("running", state);
return intent;
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.w(TAG, SubTag.bullet("#onDestroy"));
if (this.isNonStickyServiceRunning()) {
Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS RUNNING ++++++++"));
} else {
Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS NOT RUNNING ++++++++"));
}
}
private boolean isNonStickyServiceRunning() {
ActivityManager manager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (NonStickyService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
code:
public class NonStickyService extends Service {
private static final String TAG = NonStickyService.class.getSimpleName();
private HeavyWorkRunnable mHeavyWorkRunnable = null;
private String running = null;
#Override
public void onCreate() {
super.onCreate();
Log.w(TAG, SubTag.bullet("#onCreate"));
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.w(TAG, SubTag.bullet("#onStartCommand"));
running = intent.getStringExtra("running");
if (running != null && !running.isEmpty() && running.equals("start")) {
this.StartHeavyWorkThread();
}
return Service.START_NOT_STICKY;
}
private void StartHeavyWorkThread() {
Log.w(TAG, SubTag.bullet("#StartHeavyWorkThread"));
this.mHeavyWorkRunnable = new HeavyWorkRunnable();
new Thread(this.mHeavyWorkRunnable).start();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.w(TAG, SubTag.bullet("#onBind"));
return null;
}
#Override
public void onDestroy() {
Log.w(TAG, SubTag.bullet("#onDestroy"));
super.onDestroy();
this.running = "stop";
}
class HeavyWorkRunnable implements Runnable {
int counter = 0;
private Bundle b = null;
public void run() {
Log.w(TAG,SubTag.bullet("#HeavyWorkRunnable"));
while(running.equals("start")) {
b = new Bundle();
b.putInt("what", ++counter);
Log.w(TAG,SubTag.bullet("#HeavyWorkRunnable: counter: " + counter));
Log.w(TAG,SubTag.bullet("#HeavyWorkRunnable: b.getInt('what'): " + b.getInt("what")));
Message msg = handler.obtainMessage();
msg.setData(b);
handler.sendMessage(msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.i(TAG,SubTag.bullet("NonStickyService will Stop"));
stopSelf();
}
}
android.os.Handler handler = new android.os.Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int what = msg.getData().getInt("what");
Log.w(TAG,SubTag.bullet("#handler: what: " + what));
}
};
}
I am using a service in my application in order to get data from the server and save received data in my local database.
But when I am using the application and my service will run in the background the application works too slow.
This is my service class that I used:
public class InternetService extends Service implements Loader.OnLoadCompleteListener<Cursor> {
public static final int notify = 5 * 60 * 60 * 1000; //interval between two services(Here Service run every 1 Minute)
private Handler mHandler = new Handler(); //run on another Thread to avoid crash
private Timer mTimer = null; //timer handling
private ArrayList<FileModel> failedIDDownloads = new ArrayList<>();
private static final String TAG = "BroadcastService";
public static final String BROADCAST_ACTION = "my_package";
Intent intent;
int counter = 0;
private CursorLoader cursorLoader;
private EncycDatabase encycDB;
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
intent = new Intent(BROADCAST_ACTION);
}
#Override
public void onStart(Intent intent, int startId) {
cursorLoader = new CursorLoader(this, Uri.parse(EncycDatabase.CONTENT_PROVIDER_URL),
null, null, null, null);
cursorLoader.registerListener(1, this);
cursorLoader.startLoading();
mHandler.removeCallbacks(sendUpdatesToUI);
mHandler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
#Override
public void onDestroy() {
super.onDestroy();
// Stop the cursor loader
if (cursorLoader != null) {
cursorLoader.unregisterListener(this);
cursorLoader.cancelLoad();
cursorLoader.stopLoading();
}
}
#Override
public void onLoadComplete(Loader<Cursor> loader, Cursor cursor) {
encycDB = new EncycDatabase();
try {
while (cursor.moveToNext()) {
G.TOKEN = (cursor.getString(cursor.getColumnIndex("user_session_token")));
}
populateEncyclopediaData();
Thread searchTagThread = new Thread(new Runnable() {
#Override
public void run() {
populateSearchTagsEncyc();
populateSearchTags();
}
});
G.handler.postDelayed(new Runnable() {
#Override
public void run() {
checkForDownloadFiles();
}
},10 *60* 1000);
searchTagThread.start();
} catch (Exception e) { //When happened an error in getting Token!
e.printStackTrace();
}
}
private void populateEncyclopediaData() {
final APIService service = ServiceGenerator.createService(APIService.class,
new PreferenceManager(G.context).getLastUpdateForEncyclopediaData(), G.TOKEN);
service.getLastChanges()
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.io())
.subscribe(new Observer<Response<ArrayList<ServerLastChangesModel>>>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Response<ArrayList<ServerLastChangesModel>> response) {
Log.i("LOGO_Encycloedia", "Request code: " + response.code());
if (response.code() == 200) {
G.encyclopediaArray.clear();
for (int i = 0; i < response.body().size(); i++) {
EncyclopediaModel lcModel = new EncyclopediaModel();
lcModel.setEncyclopedia_id(response.body().get(i).getEncyclopediaId());
lcModel.setEncyclopedia_title(response.body().get(i).getEncyclopediaTitle());
lcModel.setEncyclopedia_modified_date(response.body().get(i).getEncyclopediaModifiedDate());
lcModel.setEncyclopedia_deleted(response.body().get(i).getEncyclopediaDeleted());
lcModel.setEncyclopedia_content_id(response.body().get(i).getEncyclopediaContentId());
lcModel.setEncyclopedia_out_desc_text_id(response.body().get(i).getEncyclopediaOutDescTextId());
lcModel.setEncyclopedia_in_desc_text_id(response.body().get(i).getEncyclopediaInDescTextId());
lcModel.setEncyclopedia_order_in_parent(response.body().get(i).getEncyclopediaOrderInParent());
lcModel.setEncyclopedia_parent_id(response.body().get(i).getEncyclopediaParentId());
lcModel.setEncyclopedia_is_inline_parent(response.body().get(i).getEncyclopediaIsInlineParent());
lcModel.setEncyclopedia_style_sheet(response.body().get(i).getEncyclopediaStyleSheet());
G.encyclopediaArray.add(lcModel);
}
}
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
try {
encycDB.insertIntoEncyclopediaDB(G.encyclopediaArray);
new PreferenceManager(G.context).writeLastUpdateForEncyclopediaData();
} catch (Exception e) {
e.printStackTrace();
}
populateContentData(encycDB.getContentIdsFromEncyclopedia());
}
});
}
As you can see, I used threads, but it doesn't help!
I can't find out where is the problem.
The Service runs in background but it runs on the Main Thread of the application. And IntentService runs on separate worker thread.
Move your code to IntentService.
I'm trying to keep a socket open during lifecycle changes in a headless fragment with setRetainInstance(true); in onCreate. However, when my app comes back the following exception occurs.
E/Client: Receiving thread loop error
java.net.SocketException: Socket closed
at libcore.io.Posix.recvfromBytes(Native Method)
at libcore.io.Posix.recvfrom(Posix.java:189)
at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:250)
at libcore.io.IoBridge.recvfrom(IoBridge.java:549)
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:481)
at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
at java.io.InputStreamReader.read(InputStreamReader.java:233)
at java.io.BufferedReader.fillBuf(BufferedReader.java:145)
at java.io.BufferedReader.readLine(BufferedReader.java:397)
at com.gm.popper_6.ConnectionFragment$Client$ReceivingThread.run(ConnectionFragment.java:183)
at java.lang.Thread.run(Thread.java:818)
Here's the code for the fragment
public class ConnectionFragment extends Fragment {
private InetAddress mGoAddress;
private int mGoPort;
private Client mClient;
private static final String TAG = "Connection";
private Server mServer;
private Socket mSocket;
private ConnectionFragmentListener listener;
private String mMessage;
public static ConnectionFragment newInstance(InetAddress address, int port){
Bundle bundle = new Bundle();
bundle.putSerializable("GoAddress", address);
bundle.putInt("GoPort", port);
ConnectionFragment fragment = new ConnectionFragment();
fragment.setArguments(bundle);
return fragment;
}
public interface ConnectionFragmentListener{
void onMessageRcvd(String message);
}
public void setConnectionFragmentListener(ConnectionFragmentListener listener){
this.listener = listener;
}
private void readBundle(Bundle bundle){
if (bundle != null){
mGoAddress = (InetAddress)bundle.getSerializable("GoAddress");
mGoPort = bundle.getInt("GoPort");
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
readBundle(getArguments());
mGoAddress = (InetAddress) getArguments().getSerializable("GoAddress");
mGoPort = getArguments().getInt("GoPort");
mServer = new Server();
}
#Override
public void onStart() {
super.onStart();
}
// THE SERVER CLASS
private class Server{ //DECLARATION
ServerSocket mServerSocket = null;
Thread mThread = null;
public Server(){ //CONSTRUCTOR
mThread = new Thread(new ServerThread());
mThread.start();
}
public void tearDown(){
mThread.interrupt();
try {
mServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "Error closing server socket");
}
}
class ServerThread implements Runnable{
#Override
public void run() {
//REMOVE OR COMMENT OUT FOR FINAL
//android.os.Debug.waitForDebugger();
try {
mServerSocket = new ServerSocket(mGoPort, 50, mGoAddress);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()){
try {
mSocket = mServerSocket.accept();
Log.d(TAG, "Connected");
if (mClient == null){
mClient = new Client();
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}
}
//THE CLIENT CLASS
private class Client { //DECLARATION
private final String CLIENT_TAG = "Client";
private Thread mSendThread;
private Thread mRecThread;
public Client() { //CONSTRUCTOR
Log.d(CLIENT_TAG, "Creating Client");
mSendThread = new Thread(new SendingThread());
mSendThread.start();
}
class SendingThread implements Runnable { //an inner class of Client
BlockingQueue<String> mMessageQueue;
private int QUEUE_CAPACITY = 10;
public SendingThread() {
mMessageQueue = new ArrayBlockingQueue<String>(QUEUE_CAPACITY);
}
#Override
public void run() {
mRecThread = new Thread(new ReceivingThread());
mRecThread.start();
while (true){
try {
String msg = mMessageQueue.take();
sendMessage(msg);
} catch (InterruptedException e) {
Log.d(CLIENT_TAG, "Sending loop interrupted, exiting");
}
}
}
} //closes SendingThread, an inner class of Client
class ReceivingThread implements Runnable{ //an inner class of Client
#Override
public void run() {
BufferedReader input;
try {
//android.os.Debug.waitForDebugger();
input = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
while (!Thread.currentThread().isInterrupted()){
String messageStr = null;
messageStr = input.readLine(); //Line 183
if (messageStr!= null){
Log.d(CLIENT_TAG, "Read from the stream: " + messageStr);
mMessage = messageStr;
updateMessages(false);
}
else{
Log.d(CLIENT_TAG, "The null!!!");
}
}
input.close();
} catch (IOException e) {
Log.e(CLIENT_TAG, "Receiving thread loop error", e);
e.printStackTrace();
}
} //closes run method
} //closes ReceivingThread, an inner class of Client
public void tearDown(){ //a method of Client
try {
getSocket().close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String msg){ //a method of Client
try {
Socket socket = getSocket(); //should return mSocket
if (socket == null) {
Log.d(CLIENT_TAG, "Socket is null");
} else if (socket.getOutputStream() == null) {
Log.d(CLIENT_TAG, "Socket output stream in null");
}
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(getSocket().getOutputStream())), true);
out.println(msg);
out.flush();
mMessage = msg;
updateMessages(true);
} catch (UnknownHostException e){
Log.d(CLIENT_TAG, "Unkown host", e);
} catch (IOException e) {
Log.d(CLIENT_TAG, "I/O exception", e);
} catch (Exception e){
Log.d(CLIENT_TAG, "Error 3", e);
}
Log.d(CLIENT_TAG, "Message sent: " + msg);
} //closes sendMessage, a method of the inner Client class
} //closes Client class, an inner class of Connection
private Socket getSocket() {
return mSocket;
}
public synchronized void updateMessages(boolean local){
Log.i(TAG, "Updating message: " + mMessage);
if (local){
mMessage = "me: " + mMessage;
}
else{
mMessage = "them: " + mMessage;
}
if (listener!= null){
listener.onMessageRcvd(mMessage);
}
} //closes updateMessages
public void sendMessage(String msg){ //CALL FROM MAIN ACTIVITY
if(mClient != null){ //TO SEND A STRING MESSAGE
mClient.sendMessage(msg);
}
}
public void tearDown(){
mServer.tearDown();
mClient.tearDown();
}
#Override
public void onDestroy() {
tearDown();
super.onDestroy();
}
} //closes class declaration
And here's the main activity
public class MainActivity extends Activity implements ChannelListener, DeviceActionListener,
ConnectionInfoListener, ConnectionFragment.ConnectionFragmentListener{
//CLASS DECLARATIONS
public static final String TAG = "Popper";
private WifiP2pManager manager;
private Boolean isWifiP2pEnabled = false;
ArrayList<Target> mTargets = new ArrayList<Target>(0);
Target mTarget;
TextView rcvd;
TextView ip;
EditText mssg;
String goAddress = "";
InetAddress goInetAddress;
int prefixedPort;
//declare and initialize an intent filter
private final IntentFilter intentFilter = new IntentFilter();
//private final IntentFilter serverFilter = new IntentFilter();
private Channel channel;
private BroadcastReceiver receiver = null;
private ConnectionInfoListener infoListener;
private Intent serverServiceIntent;
ConnectionFragment mConnection;
//????
public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) {
this.isWifiP2pEnabled = isWifiP2pEnabled;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//register app w/p2p framework with call to initialize
//channel is my apps connection to the p2p framework
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this, getMainLooper(), null);
receiver = new P2pReceiver(manager, channel, this);
rcvd = (TextView)findViewById(R.id.rcvd);
rcvd.setMovementMethod(new ScrollingMovementMethod());
//initialize filter and setup to listen for the following broadcast intents
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
Resources res = getResources();
prefixedPort = res.getInteger(R.integer.GOport);
}
#Override
public void onMessageRcvd(String message) {
addLine(message);
}
#Override
protected void onResume() {
super.onResume();
receiver = new P2pReceiver(manager, channel, this);
registerReceiver(receiver, intentFilter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.action_items, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.atn_direct_discover:
if (!isWifiP2pEnabled) {
NotificationToast.showToast(MainActivity.this, "Enable P2P!!!");
return true;
}
final TargetListFragment fragment = (TargetListFragment) getFragmentManager()
.findFragmentById(R.id.frag_list);
fragment.onInitiateDiscovery();
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
NotificationToast.showToast(MainActivity.this, "Discovery initiated");
}
#Override
public void onFailure(int reason) {
NotificationToast.showToast(MainActivity.this, "Discovery failed");
}
});
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override //this is associated with ChannelListener
public void onChannelDisconnected() { //removal causes error.
}
#Override
public void onConnectionInfoAvailable(WifiP2pInfo info) {
goAddress = info.groupOwnerAddress.getHostAddress(); //this returns a string rep of add.
goInetAddress = info.groupOwnerAddress; //this returns actual inet add.
ip = (TextView) findViewById(R.id.ip);
mssg = (EditText) findViewById(R.id.mssg);
ip.setText(goAddress + ":" + "8080"); //display GO address and IP
startConnectionFragment();
}
//this override method is triggered by TargetListFragment's DeviceActionListener
#Override
public void connect(WifiP2pConfig config) {
manager.connect(channel, config, new ActionListener() {
#Override
public void onSuccess() {
//maybe use this to gray out and disable the listview object that connected
}
#Override
public void onFailure(int reason) {
}
});}
public void startConnectionFragment(){
mConnection = ConnectionFragment.newInstance(goInetAddress, prefixedPort);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(mConnection, "TAG_1");
ft.commit();
mConnection.setConnectionFragmentListener(this);
}
public void addLine(String line){
final String msg = line;
runOnUiThread(new Runnable(){
#Override
public void run() {
rcvd.append("\n" + msg);
}
});
}
#Override
public void onTargetListClick(Target target) {
mTarget = target;
}
public void stopServer() {
if(serverServiceIntent != null)
{
stopService(serverServiceIntent);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mConnection != null){
//mConnection.tearDown();
}
stopServer();
}
public void SendMessage(View v){
EditText txt = (EditText) this.findViewById(R.id.mssg);
String str = txt.getText().toString();
mConnection.sendMessage(str);
txt.getText().clear();
}
}
Could this have something to do with detaching when the app goes on pause or stop and not re-attaching when it comes back to life? Are there other things I should be considering?
Ultimately the app needs to keep communication open to about 5 or 6 devices over p2p. if there is a better strategy I'm open to suggestions. Thanks.
Update - So I've confirmed that both the onDestroy and onDetach methods of the fragment are firing when the main activity goes onStop. Since I have a method to close the sockets on death of the fragment they are getting closed. The big question now is how to keep the fragment alive?
You should maybe create a helper class that will open/close sockets on behalf of other classes, such as that fragment, that helper class won't be subjected to any life cycle events, and can be kept running as long as the Application process is alive
I am attempting to connect to my XAMPP server and interact with the MySQL database with the classes below. However, the error notes that I receive a NullPointerException at the line:
result = imService.createNewGroup(newGroupName);
In the CreateGroup class. It should be noted that the CreateGroup class is also called right after a user inputs text into a Dialog and the service is started from there. I am fairly new to services and network connections, but is there something I'm missing that should allow to at least verify that the service is connected before trying to send the .createGroup command?
CreateGroup Class:
public class CreateGroup extends Activity {
private static final String SERVER_RES_RES_SIGN_UP_SUCCESFULL = "1";
private static final String SERVER_RES_SIGN_UP_USERNAME_CRASHED = "2";
private Manager imService;
private Handler handler = new Handler();
String newGroupName;
public ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
imService = ((MessagingService.IMBinder) service).getService();
}
public void onServiceDisconnected(ComponentName className) {
imService = null;
Toast.makeText(CreateGroup.this, R.string.local_service_stopped,
Toast.LENGTH_SHORT).show();
}
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindService(new Intent(CreateGroup.this, MessagingService.class),
mConnection, Context.BIND_AUTO_CREATE);
// Getting intent and info from the dialog
Intent i = getIntent();
Bundle extras = i.getExtras();
newGroupName = extras.getString("groupName");
Thread thread = new Thread() {
String result = new String();
#Override
public void run() {
// Send group name to the messaging
// service
try {
result = imService.createNewGroup(newGroupName);
} catch (NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("problem", "The value of result is " + result.toString());
handler.post(new Runnable() {
#Override
public void run() {
if (result == null) {
Toast.makeText(getApplicationContext(),
"It's null, not working", Toast.LENGTH_LONG)
.show();
}
if (result != null
&& result
.equals(SERVER_RES_RES_SIGN_UP_SUCCESFULL)) {
Toast.makeText(getApplicationContext(),
R.string.signup_successfull,
Toast.LENGTH_LONG).show();
// showDialog(SIGN_UP_SUCCESSFULL);
} else if (result != null
&& result
.equals(SERVER_RES_SIGN_UP_USERNAME_CRASHED)) {
Toast.makeText(getApplicationContext(),
R.string.signup_username_crashed,
Toast.LENGTH_LONG).show();
// showDialog(SIGN_UP_USERNAME_CRASHED);
} else // if
// (result.equals(SERVER_RES_SIGN_UP_FAILED))
{
Toast.makeText(getApplicationContext(),
R.string.signup_failed, Toast.LENGTH_LONG)
.show();
// showDialog(SIGN_UP_FAILED);
}
}
});
}
};
thread.start();
}
Server Case for "createGroup" method:
case "createGroup":
$SQLtest = "insert into groups(groupName, uniqueGroup, createTime)
VALUES('TestGroup', 1234567891, NOW())";
error_log("$SQLtest", 3 , "error_log");
if($result = $db -> query($SQLtest))
{
$out = SUCCESSFUL;
}
else
{
$out = FAILED;
}
break;
Messaging Service and createGroup method:
public class MessagingService extends Service implements Manager, Updater {
// private NotificationManager mNM;
public static String USERNAME;
public static final String TAKE_MESSAGE = "Take_Message";
public static final String FRIEND_LIST_UPDATED = "Take Friend List";
public static final String MESSAGE_LIST_UPDATED = "Take Message List";
public ConnectivityManager conManager = null;
private final int UPDATE_TIME_PERIOD = 15000;
private String rawFriendList = new String();
private String rawMessageList = new String();
SocketerInterface socketOperator = new Socketer(this);
private final IBinder mBinder = new IMBinder();
private String username;
private String password;
private boolean authenticatedUser = false;
// timer to take the updated data from server
private Timer timer;
private StorageManipulater localstoragehandler;
private NotificationManager mNM;
public class IMBinder extends Binder {
public Manager getService() {
return MessagingService.this;
}
}
#Override
public void onCreate() {
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
localstoragehandler = new StorageManipulater(this);
// Display a notification about us starting. We put an icon in the
// status bar.
// showNotification();
conManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
new StorageManipulater(this);
// Timer is used to take the friendList info every UPDATE_TIME_PERIOD;
timer = new Timer();
Thread thread = new Thread() {
#Override
public void run() {
Random random = new Random();
int tryCount = 0;
while (socketOperator.startListening(10000 + random
.nextInt(20000)) == 0) {
tryCount++;
if (tryCount > 10) {
// if it can't listen a port after trying 10 times, give
// up...
break;
}
}
}
};
thread.start();
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public String createNewGroup(String groupName) throws NullPointerException, UnsupportedEncodingException {
String params = "action=createGroup";
String result = socketOperator.sendHttpRequest(params);
return result;
}
}
Because your code has an inherent race condition. And an evil one.
Change to something like this:
public void onCreate(Bundle savedInstanceState) {
bindService(new Intent(CreateGroup.this, MessagingService.class),
mConnection, Context.BIND_AUTO_CREATE);
// but do not start thread here!
}
public ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
imService = ((MessagingService.IMBinder) service).getService();
startCommunicationThread(); // <----------------------- only here can you start comm. thread
}
public void onServiceDisconnected(ComponentName className) {
imService = null;
Toast.makeText(CreateGroup.this, R.string.local_service_stopped,
Toast.LENGTH_SHORT).show();
}
};
void startCommunicationThread() {
Thread thread = new Thread() {
String result = new String();
#Override
public void run() {
try {
result = imService.createNewGroup(newGroupName);
..........
}
If you want your code to be even more secure, use a connection state field:
public ServiceConnection mConnection = new ServiceConnection() {
volatile boolean isConnected;
public void onServiceConnected(ComponentName className, IBinder service) {
isConnected = true; // <---------------------
imService = ((MessagingService.IMBinder) service).getService();
startCommunicationThread();
}
public void onServiceDisconnected(ComponentName className) {
isConnected = false; // <---------------
imService = null;
Toast.makeText(CreateGroup.this, R.string.local_service_stopped,
Toast.LENGTH_SHORT).show();
}
};
And poll isConnected from within startCommunicationThread to make sure no sudden disconnects.
in my project MessagingService.IMBinder MessagingService gives error is there any java class that I should import.
I am trying to make an Activity run a certain service.
I followed the tutorial here but adapted to my code, and I can't make it work, because when I am invoking the service after starting and binding it to the activity, my Interface (IMyRemoteCallsLoggingService) object does not seem to have the connection properly created.
I have been trying to make this work for several days but I can't seem to get rid of a NullPointException.
Not sure if I made myself clear, in which case here's the code:
public class MtprojectActivity extends Activity {
[...]
private boolean started = false;
private RemoteSmsLoggingServiceConnection SmsLoggingConn = null;
private RemoteCallsLoggingServiceConnection CallsLoggingConn = null;
private IMyRemoteCallsLoggingService callsLoggingService;
private IMyRemoteSmsLoggingService smsLoggingService;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
retrievePreferences();
Button prefBtn = (Button) findViewById(R.id.prefsBtn);
prefBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Explicit intent to call the preferences
Intent preferencesActivity = new Intent(getBaseContext(),
Preferences.class);
startActivity(preferencesActivity);
}
});
}
private void retrievePreferences() {
// Get the xml/preferences.xml preferences
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
callsCheckbox = prefs.getBoolean("callsLogChk", false);
smsCheckbox = prefs.getBoolean("smsLogChk", false);
locationCheckbox = prefs.getBoolean("locationLogChk", false);
if (callsCheckbox) {
startCallsService();
bindCallsService();
try {
invokeCallsService();
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
}
private void startCallsService() {
if (started) {
Toast.makeText(MtprojectActivity.this, "Service already started",
Toast.LENGTH_SHORT).show();
} else {
Intent i = new Intent();
i.setClassName("app.mtproject", "app.mtproject.CallsLoggingService");
startService(i);
started = true;
updateCallsServiceStatus();
Log.d(getClass().getSimpleName(), "startService()");
}
}
private void bindCallsService() {
if (CallsLoggingConn == null) {
CallsLoggingConn = new RemoteCallsLoggingServiceConnection();
Intent i = new Intent();
i.setClassName("app.mtproject", "app.mtproject.CallsLoggingService");
bindService(i, CallsLoggingConn, Context.BIND_AUTO_CREATE);
updateCallsServiceStatus();
Log.d(getClass().getSimpleName(), "bindService()");
} else {
Toast.makeText(MtprojectActivity.this,
"Cannot bind - service already bound", Toast.LENGTH_SHORT)
.show();
}
}
private void invokeCallsService() throws RemoteException {
if (CallsLoggingConn == null) {
Toast.makeText(MtprojectActivity.this,
"Cannot invoke - service not bound", Toast.LENGTH_SHORT)
.show();
} else {
callsLoggingService.dumpCallsLog();
TextView t = (TextView) findViewById(R.id.notApplicable);
t.setText("It worked!");
Log.d(getClass().getSimpleName(), "invokeService()");
}
}
class RemoteCallsLoggingServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName className,
IBinder boundService) {
callsLoggingService = IMyRemoteCallsLoggingService.Stub
.asInterface((IBinder) boundService);
Log.d(getClass().getSimpleName(), "onServiceConnected()");
}
public void onServiceDisconnected(ComponentName className) {
callsLoggingService = null;
updateCallsServiceStatus();
Log.d(getClass().getSimpleName(), "onServiceDisconnected");
}
};
I get a NullPointerException right on callsLoggingService.dumpCallsLog() in the invokeCallsService() method, and I'm not sure what's the problem!
Here's the code of the service:
public class CallsLoggingService extends Service {
String date, duration, type;
private Handler serviceHandler;
private Task myTask = new Task();
#Override
public IBinder onBind(Intent arg0) {
Log.d(getClass().getSimpleName(), "onBind()");
return myRemoteCallsServiceStub;
}
private IMyRemoteCallsLoggingService.Stub myRemoteCallsServiceStub = new IMyRemoteCallsLoggingService.Stub() {
public void dumpCallsLog() throws RemoteException {
CallsLoggingService.this.dumpCallsLog();
}
};
#Override
public void onCreate() {
super.onCreate();
Log.d(getClass().getSimpleName(), "onCreate()");
}
#Override
public void onDestroy() {
super.onDestroy();
serviceHandler.removeCallbacks(myTask);
serviceHandler = null;
Log.d(getClass().getSimpleName(), "onDestroy()");
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
serviceHandler = new Handler();
serviceHandler.postDelayed(myTask, 10L);
Log.d(getClass().getSimpleName(), "onStart()");
}
class Task implements Runnable {
public void run() {
try {
myRemoteCallsServiceStub.dumpCallsLog();
} catch (RemoteException e) {
e.printStackTrace();
}
serviceHandler.postDelayed(this, 86400000L);
Log.i(getClass().getSimpleName(), "Calling the dumpCallsLog");
}
}
private synchronized void dumpCallsLog() {
ContentResolver cr = getContentResolver();
String columns[] = new String[] { CallLog.Calls.DATE,
CallLog.Calls.DURATION, CallLog.Calls.TYPE };
Uri mContacts = CallLog.Calls.CONTENT_URI;
Cursor c = cr.query(mContacts, columns, // Which columns to return
null, // WHERE clause; which rows to return(all rows)
null, // WHERE clause selection arguments (none)
CallLog.Calls.DEFAULT_SORT_ORDER // Order-by clause
// (ascending
// by name)
);
if (c.moveToFirst()) {
do {
// Get the field values
date = c.getString(c.getColumnIndex(CallLog.Calls.DATE));
duration = c
.getString(c.getColumnIndex(CallLog.Calls.DURATION));
type = c.getString(c.getColumnIndex(CallLog.Calls.TYPE));
} while (c.moveToNext());
}
}
}
Thanks a lot everybody for the help!
bindService() is asynchronous. You cannot use callsLoggingService until onServiceConnected() is called.