The Bluetooth device I am trying to connect has always the same pincode. This should make it possible to pair the device by setting the pin programmatically.
After trying to search how this could be done, I ended up with the code below:
BluetoothDevice device = getDevice();
//To avoid the popup notification:
device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
device.getClass().getMethod("cancelPairingUserInput", boolean.class).invoke(device, true);
byte[] pin = ByteBuffer.allocate(4).putInt(1234).array();
//int pinn = 1234;
//Entering pin programmatically:
Method ms = device.getClass().getMethod("setPin", byte[].class);
//Method ms = device.getClass().getMethod("setPasskey", int.class);
ms.invoke(device, pin);
//Bonding the device:
Method mm = device.getClass().getMethod("createBond", (Class[]) null);
mm.invoke(device, (Object[]) null);
cancelPairingUserInput gives me a NoSuchMethodException, which is weird because the method does exist in BluetoothDevice class.
Is looks like Setpin or SetPasskey doesn't do anything. The device just wont pair. It only pairs after manually entering the pin.
So the only line of code that works is:
//Bonding the device:
Method mm = device.getClass().getMethod("createBond", (Class[]) null);
mm.invoke(device, (Object[]) null);
Logcat output:
09-27 12:34:46.408: ERROR/App(11671): cancelPairingUserInput [boolean]
java.lang.NoSuchMethodException: cancelPairingUserInput [boolean]
at java.lang.Class.getConstructorOrMethod(Class.java:460)
at java.lang.Class.getMethod(Class.java:915)
at test.app.bluetooth.model.BluetoothDiscoveryAndPairing.pair(BluetoothDiscoveryAndPairing.java:97)
at test.app.bluetooth.model.BluetoothDiscoveryAndPairing.access$000(BluetoothDiscoveryAndPairing.java:25)
at test.app.bluetooth.model.BluetoothDiscoveryAndPairing$1.onReceive(BluetoothDiscoveryAndPairing.java:79)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:756)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
So what am I doing wrong?
The hidden method cancelPairingUserInput does not exist in your device. Don't use it.
You should register BroadcastReceiver for android.bluetooth.device.action.PAIRING_REQUEST
Call createBond()
Wait for BroadcastReceiver to trigger
In BroadcastReceiver if action is android.bluetooth.device.action.PAIRING_REQUEST
call this method
public void setBluetoothPairingPin(BluetoothDevice device)
{
byte[] pinBytes = convertPinToBytes("0000");
try {
Log.d(TAG, "Try to set the PIN");
Method m = device.getClass().getMethod("setPin", byte[].class);
m.invoke(device, pinBytes);
Log.d(TAG, "Success to add the PIN.");
try {
device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
Log.d(TAG, "Success to setPairingConfirmation.");
} catch (Exception e) {
// TODO Auto-generated catch block
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
}
It also works on a device with Jelly Bean version (4.1.2) of Android.
this is works for me:
IntentFilter filter2 = new IntentFilter(
"android.bluetooth.device.action.PAIRING_REQUEST");
mActivity.registerReceiver(
pairingRequest, filter2);
private final BroadcastReceiver pairingRequest = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.bluetooth.device.action.PAIRING_REQUEST")) {
mBluetoothDevice = needed;
try {
byte[] pin = (byte[]) BluetoothDevice.class.getMethod("convertPinToBytes", String.class).invoke(BluetoothDevice.class, "1234");
Method m = mBluetoothDevice.getClass().getMethod("setPin", byte[].class);
m.invoke(mBluetoothDevice, pin);
mBluetoothDevice.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(mBluetoothDevice, true);
}
catch(Exception e)
{
e.printStackTrace();
}
Related
I'm making a simple app client-server in java, i want my phone to receive and send messages to my pc, i'm on same LAN and my pc's ip is 192.168.1.8, my serverSocket is running on port 7777.
for some reason my client android cant connect i think it is because i created a socket in a thread, i have read that i should use AsyncTask or Handle, i tried with that too but i get an exception too.
Class server:
public class MyServer implements Runnable{
private ServerSocket server;
private ObjectInputStream in;
private ObjectOutputStream out;
private Socket clientedConnected;
public ExampleServerZNuC(){
try {
server= new ServerSocket(7777);
System.out.println("server opened on port 7777");
} catch (IOException ex) {
Logger.getLogger(MyServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sendMessage(String message){
try {
out.writeObject(message);
out.flush();
} catch (IOException ex) {
Logger.getLogger(MyServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sendNotifiy(){
try {
out.writeObject("Send Notify");
out.flush();
} catch (IOException ex) {
Logger.getLogger(MyServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String getMessage(){
return "";
}
public void run(){
System.out.println("method run started");
System.out.println("Waiting for a client to connect");
try {
Socket clientedConnected;
clientedConnected = server.accept();
System.out.println("A client connected : "+clientedConnected.getInetAddress().getHostAddress());
in= new ObjectInputStream(clientedConnected.getInputStream());
out = new ObjectOutputStream(clientedConnected.getOutputStream());
} catch (IOException ex) {
Logger.getLogger(MyServer.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("End of method Run");
} }
this is the output i get when i create run the server:
server opened on port 7777
method run started
Waiting for a client to connect
client android:
class to connect to my server( atm i just want it to receive the message):
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.net.Socket;
import java.net.UnknownHostException;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class MyConnect implements Runnable{
private Socket myconnect=null ;
private TextView txtMessage;
private ObjectInputStream in;
private ObjectOutputStream out;
public MyConnect( ){
try {
// this is my pc's IP, my phone is connected to same LAN
Log.d("inizializating socket","");
myconnect= new Socket("192.168.1.8",7777);
in = new ObjectInputStream(myconnect.getInputStream());
out = new ObjectOutputStream(myconnect.getOutputStream());
} catch (UnknownHostException e) {
Log.d("My Error connecting",e.getMessage());
} catch (IOException e) {
Log.d("My Error connecting",e.getMessage());
}
}
#Override
public void run() {
try {
String message = (String)in.readObject();
Log.d("messaged recived",message);
} catch (OptionalDataException e) {
Log.d("My Error connecting",e.getMessage());
} catch (ClassNotFoundException e) {
Log.d("Error My ClassNotFoundException",e.getMessage());
} catch (IOException e) {
Log.d("Error My IOEXCEPTION",e.getMessage());
}
}
}
this is the error that i get when i click on a button that should create the socket:
on create i use connect= new MyConnect();
and on onclick event i use:
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.btnExample:
new Thread(connect).start();
break;
}
}
error message :
05-29 19:02:05.905: E/AndroidRuntime(6520): FATAL EXCEPTION: main
05-29 19:02:05.905: E/AndroidRuntime(6520): android.os.NetworkOnMainThreadException
05-29 19:02:05.905: E/AndroidRuntime(6520): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1118)
05-29 19:02:05.905: E/AndroidRuntime(6520): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
05-29 19:02:05.905: E/AndroidRuntime(6520): at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
05-29 19:02:05.905: E/AndroidRuntime(6520): at libcore.io.IoBridge.connect(IoBridge.java:112)
05-29 19:02:05.905: E/AndroidRuntime(6520): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
05-29 19:02:05.905: E/AndroidRuntime(6520): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
05-29 19:02:05.905: E/AndroidRuntime(6520): at java.net.Socket.startupSocket(Socket.java:566)
05-29 19:02:05.905: E/AndroidRuntime(6520): at java.net.Socket.tryAllAddresses(Socket.java:127)
EDIT:
class MySyncTask extends AsyncTask<Integer, Integer, String>{
String advice;
#Override
protected String doInBackground(Integer... params) {
try {
s = new Socket("192.168.1.8",7777);
Log.d("socket connected","");
ObjectInputStream streamReader = new ObjectInputStream(s.getInputStream());
advice = (String)streamReader.readObject();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
protected void onPostExecute(String result) {
txtMessage.setText("you got a message: " + advice);
}
protected void onPreExecute() {
Log.d("my started","start");
}
}
and i used
MySyncTask asyncTask=new MySyncTask ();
asyncTask.execute();
on onCreate() method but for some reason it is not connecting to my server
LogCat with AsyncTask:
05-29 19:46:21.900: D/my started(26169): start
05-29 19:46:22.020: D/libEGL(26169): loaded /system/lib/egl/l ibEGL_mali.so
05-29 19:46:22.030: D/libEGL(26169): loaded /system/lib/egl/libGLESv1_CM_mali.so
05-29 19:46:22.040: D/libEGL(26169): loaded /system/lib/egl/libGLESv2_mali.so
05-29 19:46:22.080: D/OpenGLRenderer(26169): Enabling debug mode 0
EDIT PROBLEM SOLVED
after searching on internet why socket was not connecting i found someone who had a similar problem and i found the answer here Android Socket not being instantiated
i had to initializate the socket first and then use connect
This is happening because you are trying to perform a networking operation on the main thread. This is bad design, you do not want to lock up the user interface while you run a process that can take long time to execute.
Put your network method in an AsyncTask or Service.
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Like Eduardo points out,
NetworkOnMainThreadException
The exception that is thrown when an application attempts to perform a
networking operation on its main thread.
Use Asynctask for your connection
Be sure to have
<uses-permission android:name="android.permission.INTERNET" />
into your AndroidManifest.xml
Have you set the proper permissions in the manifest? If yes, is the phone on the same network as your PC (if they are on same wifi network is good)? Try running through debugger and putting a break point.
Here is a nice tutorial that explains client/server communication in android.
http://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/
Good luck
-Raghu
I am getting a Java null pointer exception Unable to start receiver error. I am making an app which receives the push from the parse.com and I am getting the error for Android 4.0.3 - 4.0.4, and also when I restart the some devices..
My LogCat is
**java.lang.RuntimeException: Unable to start receiver com.omega.omegaplus.main.MyCustomReceiver: java.lang.NullPointerException
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2419)
at android.app.ActivityThread.access$1500(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1322)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:4987)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at org.json.JSONTokener.nextCleanInternal(JSONTokener.java:116)
at org.json.JSONTokener.nextValue(JSONTokener.java:94)
at org.json.JSONObject.<init>(JSONObject.java:154)
at org.json.JSONObject.<init>(JSONObject.java:171)
at com.omega.omegaplus.main.MyCustomReceiver.onReceive(MyCustomReceiver.java:30)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2408)
... 10 more**
My broadcast receiver is
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String message = extras != null ? extras.getString("com.parse.Data")
: "";
Log.e("message ", " " + message);
JSONObject jObject;
try {
jObject = new JSONObject(message);
//objectId = jObject.getString("id");
time = jObject.getString("time");
msg = jObject.getString("title");
title = jObject.getString("msg");
GCMMessage gcmMessage = new GCMMessage();
//gcmMessage.setMsg_id(1);
gcmMessage.setMsg_body(msg);
gcmMessage.setMsg_title(title);
gcmMessage.setType(0);
gcmMessage.setDateTime(time);
DatabaseUtil.insertMessage(context, gcmMessage);
}
catch (JSONException e) {
e.printStackTrace();
}
}
When I reboot my phone then also it showing same error..., otherwise it is working fine.
I'll have a guess that message has the value of "" or NULL
JSONObject jObject;
try {
if (message != null && !message.equals("") {
jObject = new JSONObject(message);
//objectId = jObject.getString("id");
time = jObject.getString("time");
msg = jObject.getString("title");
title = jObject.getString("msg");
GCMMessage gcmMessage = new GCMMessage();
//gcmMessage.setMsg_id(1);
gcmMessage.setMsg_body(msg);
gcmMessage.setMsg_title(title);
gcmMessage.setType(0);
gcmMessage.setDateTime(time);
DatabaseUtil.insertMessage(context, gcmMessage);
}
}
catch (JSONException e) {
e.printStackTrace();
}
I have an application that needs to connect to the Internet to perform some actions but when no Internet available it will crash. I read that I need to use try catch bracket in case no Internet. I tried to use it as you can see in AsyncTask but it doesn't work. I don't know why. The app crashes. How to deal with try catch where to put it in my code?
One more thing what about if the app lost Internet connection while process is going on. How supposed I to deal with this thing so my app doesn't crash. Thank you very much.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
lv = (ListView) findViewById(R.id.mybookslistview);
new connectToServer().execute();
}
class connectToServer extends AsyncTask<Void, Void, Void>{
CustomListViewAdapter adapter;
HttpResponse response;
#Override
protected Void doInBackground(Void... params) {
ids_list.clear();
names_list.clear();
writers_list.clear();
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(link);
ArrayList<NameValuePair> list = new ArrayList<NameValuePair>();
list.add(new BasicNameValuePair(word, connectionPurpose));
try {
post.setEntity(new UrlEncodedFormEntity(list, HTTP.UTF_8));
response = client.execute(post);
BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
sb = new StringBuffer();
String tempVar = "";
while((tempVar = br.readLine()) != null){
sb.append(tempVar);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//Get data from stringbuffer and put it in array list
if(!sb.toString().trim().contentEquals("null")){
content_array = sb.toString().split(",");
for(int s = 0; s < content_array.length; s++){
if(content_array[s].contains("-")){
String temp[] = content_array[s].split("-");
ids_list.add(temp[0].trim());
names_list.add(temp[1].trim());
writers_list.add(temp[2].trim());
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if(!mWifi.isConnected()){
adb = new AlertDialog.Builder(Home.this);
adb.setMessage("لا يوجد إنترنت. قم بتفعيل الإنترنت ثم حاول مرة أخرى.");
adb.setPositiveButton("حاول مجددا", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
new connectToServer().execute();
}
});
adb.setNegativeButton("إغلاق التطبيق", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
//It shows dialog if no connection
adb.create().show();
}else{
list = new ArrayList<Home.ListViewItem>();
for(x = 0; x < ids_list.size(); x++){
list.add(new ListViewItem(){{bookName = names_list.get(x); writerName = writers_list.get(x);}});
}
adapter = new CustomListViewAdapter(Home.this, list);
lv.setAdapter(adapter);
if(sb.toString().trim().contentEquals("null")){
Toast.makeText(Home.this, "لا توجد نتائج.", Toast.LENGTH_LONG).show();
}
}
This is my logcat:
java.net.UnknownHostException: Unable to resolve host "globalmall.ca": No address associated with hostname
at java.net.InetAddress.lookupHostByName(InetAddress.java:424)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
at java.net.InetAddress.getAllByName(InetAddress.java:214)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:670)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:509)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
at readit.Mansour.inc.Home$connectToServer.doInBackground(Home.java:106)
at readit.Mansour.inc.Home$connectToServer.doInBackground(Home.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname)
at libcore.io.Posix.getaddrinfo(Native Method)
at libcore.io.ForwardingOs.getaddrinfo(ForwardingOs.java:55)
at java.net.InetAddress.lookupHostByName(InetAddress.java:405)
... 18 more
Caused by: libcore.io.ErrnoException: getaddrinfo failed: ENETUNREACH (Network is unreachable)
... 21 more
threadid=13: thread exiting with uncaught exception (group=0x40e582a0)
You can either create method or some class may be where you can instantiate method as static.
Here is a method named isConnectedToInternet() which checks whether internet is connected or not. Return boolean on the basis of connection back to the calling function.
Snippet:
public boolean isConnectedToInternet(){
ConnectivityManager connectivity = (ConnectivityManager)getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null)
{
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null)
for (int i = 0; i < info.length; i++)
if (info[i].getState() == NetworkInfo.State.CONNECTED)
{
return true;
}
}
return false;
}
You can decide on the basis of return value of isConnectedToInternet() whether to execute AysncTask or Throw some pop up. Here i've been added user to brought in his Data Settings.
Something like these:
if(isConnectedToInternet())
{
// Run AsyncTask
}
else
{
// Here I've been added intent to open up data settings
Intent intent=new Intent(Settings.ACTION_MAIN);
ComponentName cName = new ComponentName("com.android.phone","com.android.phone.NetworkSetting");
intent.setComponent(cName);
}
As you mentioned what if you looses connection in between. You can check the status code as per the reponse of httpclient and pop up relevant information to user.
You can integrate these snippet under AysncTask.
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpResponse response = null;
response = httpclient.execute(httpget);
int code = response.getStatusLine().getStatusCode();
public class CheckNetClass {
public static Boolean checknetwork(Context mContext) {
NetworkInfo info = ((ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.getActiveNetworkInfo();
if (info == null || !info.isConnected()) {
return false;
}
if (info.isRoaming()) {
// here is the roaming option, you can change it if you want to
// disable internet while roaming, just return false
return true;
}
return true;
}
}
Use this class to check internet availability like:
if (CheckNetClass.checknetwork(getApplicationContext()))
{
new GetCounterTask().execute();
}
else
{
Toast.makeText(getApplicationContext(),"Sorry,no internet connectivty",1).show();
}
Hope this helps..
Interesting. You have in your stack trace these lines:
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
readit.Mansour.inc.Home$connectToServer.doInBackground(Home.java:106)
Which mean that the offending line is
response = client.execute(post);
Which is different from the line that you mentioned. Verify the stack trace & the line that it mentions. Also, see that if you fix it by catching Exception. If you don't, then you have a bigger problem, because UnknownHostException is a subclass of IOException, which you already catch.
This is my code to access Google Drive, taken largely from ArtOfWarfare in this post:
public class MainActivity extends Activity {
class OnTokenAcquired implements AccountManagerCallback<Bundle> {
boolean alreadyTriedAgain;
public OnTokenAcquired() {
// TODO Auto-generated constructor stub
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 3025) {
switch (resultCode) {
case RESULT_OK:
AccountManager am = AccountManager.get(getApplicationContext());
am.getAuthToken(am.getAccounts()[0],
"ouath2:" + DriveScopes.DRIVE,
new Bundle(),
true,
new OnTokenAcquired(),
null);
break;
case RESULT_CANCELED:
// This probably means the user refused to log in. Explain to them why they need to log in.
break;
default:
// This isn't expected... maybe just log whatever code was returned.
break;
}
} else {
// Your application has other intents that it fires off besides the one for Drive's log in if it ever reaches this spot. Handle it here however you'd like.
}
}
#Override
public void run(AccountManagerFuture<Bundle> result) {
try {
final String token = result.getResult().getString(AccountManager.KEY_AUTHTOKEN);
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
Drive.Builder b = new Drive.Builder(httpTransport, jsonFactory, null);
b.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
#Override
public void initialize(JsonHttpRequest request) throws IOException {
DriveRequest driveRequest = (DriveRequest) request;
driveRequest.setPrettyPrint(true);
driveRequest.setKey("my number here");
driveRequest.setOauthToken(token);
}
});
final Drive drive = b.build();
final com.google.api.services.drive.model.File body = new com.google.api.services.drive.model.File();
body.setTitle("My Test File");
body.setDescription("A Test File");
body.setMimeType("text/plain");
File newFile = new File("this");
final FileContent mediaContent = new FileContent("text/plain", newFile);
new Thread(new Runnable() {
public void run() {
try {
com.google.api.services.drive.model.File file = drive.files().insert(body, mediaContent).execute();
alreadyTriedAgain = false; // Global boolean to make sure you don't repeatedly try too many times when the server is down or your code is faulty... they'll block requests until the next day if you make 10 bad requests, I found.
} catch (IOException e) {
if (!alreadyTriedAgain) {
alreadyTriedAgain = true;
AccountManager am = AccountManager.get(getApplicationContext());
am.invalidateAuthToken(am.getAccounts()[0].type, null); // Requires the permissions MANAGE_ACCOUNTS & USE_CREDENTIALS in the Manifest
am.getAuthToken(am.getAccounts()[0],
"ouath2:" + DriveScopes.DRIVE,
new Bundle(),
true,
new OnTokenAcquired(),
null);
} else {
// Give up. Crash or log an error or whatever you want.
}
}
}
}).start();
Intent launch = (Intent)result.getResult().get(AccountManager.KEY_INTENT);
if (launch != null) {
startActivityForResult(launch, 3025);
return; // Not sure why... I wrote it here for some reason. Might not actually be necessary.
}
} catch (OperationCanceledException e) {
// Handle it...
} catch (AuthenticatorException e) {
// Handle it...
} catch (IOException e) {
// Handle it...
}
}
}
private java.io.File downloadGFileToJFolder(Drive drive, String token, File gFile, java.io.File jFolder) throws IOException {
if (gFile.toURI() != null && gFile.toURI().toString().length() > 0 ) {
if (jFolder == null) {
jFolder = Environment.getExternalStorageDirectory();
jFolder.mkdirs();
}
try {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(gFile.toURI());
get.setHeader("Authorization", "Bearer " + token);
org.apache.http.HttpResponse response = client.execute(get);
InputStream inputStream = response.getEntity().getContent();
jFolder.mkdirs();
java.io.File jFile = new java.io.File(jFolder.getAbsolutePath() + "/" + gFile.getName()); // getGFileName() is my own method... it just grabs originalFilename if it exists or title if it doesn't.
FileOutputStream fileStream = new FileOutputStream(jFile);
byte buffer[] = new byte[1024];
int length;
while ((length=inputStream.read(buffer))>0) {
fileStream.write(buffer, 0, length);
}
fileStream.close();
inputStream.close();
return jFile;
} catch (IOException e) {
// Handle IOExceptions here...
return null;
}
} else {
// Handle the case where the file on Google Drive has no length here.
return null;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getApplicationContext();
AccountManager am = AccountManager.get(this);
am.getAuthToken(am.getAccounts()[0],
"ouath2:" + DriveScopes.DRIVE,
new Bundle(),
true,
new OnTokenAcquired(),
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.activity_main, menu);
return true;
}
}
I get the following error when I launch the app (Android System also stops momentarily):
11-26 22:31:03.093: E/AndroidRuntime(4288): FATAL EXCEPTION: main
11-26 22:31:03.093: E/AndroidRuntime(4288): java.lang.RuntimeException: Unable to start activity ComponentInfo{android/android.accounts.GrantCredentialsPermissionActivity}: java.lang.NullPointerException
11-26 22:31:03.093: E/AndroidRuntime(4288): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2225)
11-26 22:31:03.093: E/AndroidRuntime(4288): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2260)
11-26 22:31:03.093: E/AndroidRuntime(4288): at android.app.ActivityThread.access$600(ActivityThread.java:139)
11-26 22:31:03.093: E/AndroidRuntime(4288): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1277)
11-26 22:31:03.093: E/AndroidRuntime(4288): at android.os.Handler.dispatchMessage(Handler.java:99)
11-26 22:31:03.093: E/AndroidRuntime(4288): at android.os.Looper.loop(Looper.java:156)
11-26 22:31:03.093: E/AndroidRuntime(4288): at android.app.ActivityThread.main(ActivityThread.java:5045)
11-26 22:31:03.093: E/AndroidRuntime(4288): at java.lang.reflect.Method.invokeNative(Native Method)
11-26 22:31:03.093: E/AndroidRuntime(4288): at java.lang.reflect.Method.invoke(Method.java:511)
11-26 22:31:03.093: E/AndroidRuntime(4288): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
11-26 22:31:03.093: E/AndroidRuntime(4288): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
11-26 22:31:03.093: E/AndroidRuntime(4288): at dalvik.system.NativeStart.main(Native Method)
11-26 22:31:03.093: E/AndroidRuntime(4288): Caused by: java.lang.NullPointerException
11-26 22:31:03.093: E/AndroidRuntime(4288): at android.accounts.GrantCredentialsPermissionActivity.onCreate(GrantCredentialsPermissionActivity.java:84)
11-26 22:31:03.093: E/AndroidRuntime(4288): at android.app.Activity.performCreate(Activity.java:4543)
11-26 22:31:03.093: E/AndroidRuntime(4288): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1071)
11-26 22:31:03.093: E/AndroidRuntime(4288): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2181)
11-26 22:31:03.093: E/AndroidRuntime(4288): ... 11 more
In addition, my phone shows a strange notification: "Permission Requested for account Weather". Anyone have any idea what's causing this?
Try replacing this:
am.getAccounts()[0],
with this:
am.getAccountsByType("com.google")[0],
My code in the other topic was over simplified to assume that the first account it found would be a Google Account (and so have a Google Drive). The code we actually used in the app checked to make sure it was a Google Account (and then performed further checks to make sure it was a company account, which is why I simplified the code to what I shared.)
I am working on a project in which I have a TCP connection with a server via Android.
I am using the following code:
public class MyService extends Service {
private static final String TAG = "MyService";
MediaPlayer player;
Socket s;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
player = MediaPlayer.create(this, R.raw.braincandy);
player.setLooping(false); // Set looping
}
#Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
player.stop();
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
player.start();
try {
s = new Socket("192.168.1.54", 64000);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I am running the connection as a service.
The real problem is I can make a connection with my Android phone (2.3.7) and with the emulator (2.3.3) but when I want to test in on my tablet (4.0.3), my app always crashes when I want to start the connection.
Can someone help me with this?
Here is the logcat log:
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start service
com.gunther.servicetcp.MyService#412b0a98 with Intent
{ cmp=com.gunther.servicetcp/.MyService }: android.os.NetworkOnMainThreadException
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2376)
at android.app.ActivityThread.access$1900(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.os.NetworkOnMainThreadException
0at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
at libcore.io.IoBridge.connect(IoBridge.java:112)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.Socket.startupSocket(Socket.java:566)
at java.net.Socket.tryAllAddresses(Socket.java:127)
at java.net.Socket.<init>(Socket.java:177)
at java.net.Socket.<init>(Socket.java:149)
at com.gunther.servicetcp.MyService.onStart(MyService.java:53)
at android.app.Service.onStartCommand(Service.java:438)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2359)
: ... 10 more
You shouldn't do network operations on the main thread. This will lead to your app being unresponsive. Before Honeycomb you could get away with it, but Honeycomb and newer Android versions will check and throw the exception you're getting. See also this page of the Android Developers API
Services's onStart() method runs on the main thread, (yes, services seem to run on the main thread of the application.) so you should fork another thread in the onStart() method and do everything you need to do in that thread.