bluetooth file sending via BluetoothShare class is not working - java

I am developing an application where i have file uri as well as bt device address with me. I need to send the file to the defined bt device. But, the device picker screen should not be shown. It should directly start the device sending.
Obviously, intent:ACTION_SEND is not an option here, as it will show the chooser dialog. The main intension of the application is to bypass the chooser dialog and enable user to send selected file to selected device directly.
So, i was trying the following solution suggested in stack-overflow:
/*BluetoothDevice device;
String filePath = Environment.getExternalStorageDirectory().toString() + "/file.jpg";
ContentValues values = new ContentValues();
values.put(BluetoothShare.URI, Uri.fromFile(new File(filePath)).toString());
values.put(BluetoothShare.DESTINATION, device.getAddress());
values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_OUTBOUND);
Long ts = System.currentTimeMillis();
values.put(BluetoothShare.TIMESTAMP, ts);
Uri contentUri = getContentResolver().insert(BluetoothShare.CONTENT_URI, values);*/
But unfortunately, it is not working. After getContentResolver().insert, there is no action taken. Needless to say, i have tried various permissions and other stuffs, but to no effect.
So, people who have used this code, please provide your suggestions. Any help to meet the requirement will be very much appreciated.

Does it produce any exception? Please share your Logcat output.
By the way, make use you have the following permission in AndroidManifest.xml
<uses-permission android:name="android.permission.BLUETOOTH"/>
If you are doing a device discovery, add this too in the manifest file
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

I also found this problem. I can show some evidence to solve this problem. After trying this code check outbound transfer queue of your device (to open it, Send a file manually to a device and click the notification icon). Then you can see device has tried to send objects and those were failed. Click on one failure message and you can see pop-up with no file path. I think the problem is though here we are setting the file path using URI to the contentValues it will not be checked in the process. We have to do some thing for this.

Related

URI to image on activity started blank

API 30
This is going to all sound very scrambled, because I've very conf
The following works perfectly fine, it loads the image into 'imCardImage' widget without problem.
val getContentCardImage = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
imCardImage.setImageURI(uri) // Handle the returned Uri
cImageCardStr = uri.toString()
Log.d("EditCards","URI = "+uri.toString())
Log.d("EditCards","(mydecklist) URI = "+mydecklist[cCardPosition].c_image)
}
The problem appears when, I exit the app and restart it/go to another activity within the same application, all the images are gone it's as if I had temporary permission while the activity was active, in the area where you can select images and revoked the instant that activity is terminated, and yet I've requested permission from the use and been granted it.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
I did get this error; Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider but for some odd reason it's stopped happening for some unknown reason.
override fun onBindViewHolder( holder: ViewHolder, position: Int ) {
holder.cardTitle.text = "[$position] "+mydecklist[position].c_title
holder.cardMessage.text = mydecklist[position].c_message
holder.cardImage.setImageURI(mydecklist[position].c_image.toUri())
}
The above is supposed to load the image from mydecklist[#].c_image in to a RecycleView / CardView, but is blank when starting the app.
14727-14727/com.example.cardgamexxx E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.cardgamexxx, PID: 14727
java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{bc01e1c 14727:com.example.cardgamexxx/u0a734} (pid=14727, uid=10734) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs
-- error is back, thanks to "mehul bisht" no actually I did want that back :) see my reply to your comment.
// Permissions
permissionsLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
readPermissionGranted = permissions[Manifest.permission.READ_EXTERNAL_STORAGE] ?: readPermissionGranted
}
requestPermissions()
Permission already requested, if there is some other permission I should be asking for I'd love to know.
EDIT 2
Pretty sure I might have an idea, I might be entirely wrong though!
registerForActivityResult()...
Above when the user selects the image the image is resolved? uri is valid? I have permission at this point? no idea why that works but it works.
holder.cardImage.setImageURI(mydecklist[position].c_image.toUri())
That's the deploy line that sends the image to the cardImage widget, but is in a mutable list as a type string which I am converting to a Uri. I suppose that is okay. however it doesn't work when loading the application from a restart or just switching to another activity in the same application and back again, so either I need to resolve the uri so that it's valid again or takepermission to have access to it always.
NB: it would be better if I had my own folder that users could drop files in that I had total access to but I don't know how to do that so, I have to go the overly convoluted obtuse route.

How to download files in background regardless of Application state?

This has been asked a couple of times on Unity Questions, but never answered.
All I need to do is creare an Android pluugin which downloads few files from given urls and show a downloading progress in notification panel. Downloading should continue even if my Unity application is out of focus.
(source: cuelogic.com)
Here is a peice of code that I have right now:
void DownloadFiles(string[] urls)
{
foreach(var url in urls)
{
StartCoroutine(DownloadFile_CR(url));
}
}
IEnumerator DownloadFile_CR(string url)
{
WWW www = new WWW(url);
while(!www.isDone)
{
yield return null;
}
if(www.error == null)
{
//file downloaded. do something...
}
}
These are some texture files. So How do I get the texture result back from native android code?
Any king of help is appreciated.
I had the same problem. At first, I used a service that worked in the background and downloaded the files I needed, including calculating progress and on complete events.
Then, I made my plugin a little more simple and easy to use. You make an instance of a Java object, providing it with the GameObject name and method name for the responses. I used json to serialize and deserialize java and C# objects, because only strings can be passed between Unity's MonoBehaviour objects and java objects.
Here is how the downnload looks in the android plugin:
Uri Download_Uri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
//Restrict the types of networks over which this download may proceed.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
//Set whether this download may proceed over a roaming connection.
request.setAllowedOverRoaming(true);
//Set the local destination for the downloaded file to a path within the application's external files directory
String[] split = url.split("/");
request.setDestinationInExternalFilesDir(activity, null, split[split.length-1]);
//Set the title of this download, to be displayed in notifications (if enabled).
request.setTitle("Downloading " + title);
//Set a description of this download, to be displayed in notifications (if enabled)
request.setDescription("Downloading " + name);
request.setVisibleInDownloadsUi(false);
//Enqueue a new download and get the reference Id
long downloadReference = downloadManager.enqueue(request);
Then you could send back to unity the reference Id so you can get the progress and check if a file is still downloading once your app is been restarted (use SharedPreferences \ PlayerPrefs to store them)
If you want it to continue even when unity is not in focus then you cannot do it in C# in Unity with the WWW class.
If i wanted to do this i would probably write a native Android plugin that starts a download service.
From the official google docs:
A Service is an application component that can perform long-running
operations in the background, and it does not provide a user
interface. Another application component can start a service, and it
continues to run in the background even if the user switches to
another application.
Services are not that complex, you start them with Intents just as you would an activity and there are lots of examples online for this type of service.
Here is the official Android documentation regarding services: https://developer.android.com/guide/components/services.html

How to queue up data for server dispatch on android

I am working on an android app with an email feature. I want my users to be able to compose and send emails while in airplane mode. For that I need some sort of queue that can check if there is network and send, etc. I image this must have been done 100s of times. But I am not really sure why my searches aren't turning up much. Does anyone know of a library or git project that I can use to accomplish this? If not, does anyone know how to accomplish this?
I believe it is called the Queue and send pattern.
Update
I am starting a bounty on this question. What I hope for is a working example that does not use SMS. For my particular case I am working on an Appengine Connected Android Project. The client needs to send data (String, Bitmap, etc under a particular POJO say Dog) to the server. I want to be able to queue up these data somehow. I can use Gson to save data to file, etc. The bottom line is that I need to be able to check for network. When there is network I dequeue my queue into the server. If there is no network, I keep saving into the queue.
My queue can be Queue<Dog>, where Dog is my class with fields such as Bitmap (or path to image), String, long, etc.
I am looking for a working example. It can be very simple, but the example must work. A git zip would be great. I am giving up close to half of my points for this question.
class Dog{
String dogname;
String pathToImage;
int dogAge;
//etc.
}
//Design pattern for sending Dog to server
0) Unmarshall queue from file using Gson
1) Add dog to queue
2) If there is network, loop through queue and send data to server
3) if there is no network save queue to file
//Ideally, as soon as there is network, the method should be able to detect so and run to send data to server
First you need to set up a receiver to watch the wifi connection to see when they have data, you could also check for normal 3g/4g connections and make a broadcast receiver for that as well. todo this let use implement a broadcast receiver for connection status changes. put something like this in the manifest in the application tag
<receiver android:name=".NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
now we need to make the receiver we just defined in the manifest
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//here, check that the network connection is available. If yes, start your email service. If not, stop your email service.
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info != null) {
if (info.isConnected()) {
//start service
Intent intent = new Intent(this, ItemServiceManager.class);
startService(intent);
}
else {
//stop service
Intent intent = new Intent(this, ItemServiceManager.class);
stopService(intent);
}
}
}
}
What this does is puts a big fat antenna called NetworkChangeReceiver out in android land, that is fine tuned to listen in on when android has something to say about a change in the data connection status.
now you need to build your ItemServiceManager.class which should read from a database (it should also extend Service. It should choose the oldest item in the database, (email it, text it, upload to server, whatever), and if the connection was successful then remove the item from the database, and load the next oldest one. If there is no more then close the service and the broadcast receiver.
If you have a connection and the user needs to send more data, then add it to the database, and then make sure the service is started. Maybe notify it that it should double check the database (after a few seconds) before deciding it can close because nothing is there.
This is how you might disable your broadcast receiver.
PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(context, NetworkChangeReceiver.class);
packageManager.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
When a new item is to be uploaded, if there is no web connection, the email should be saved to the database and the broadcast receiver should be started to know when internet is back so it can know when to upload. You might start it up like this.
PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(context, NetworkChangeReceiver.class);
packageManager.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP);
The whole point is you only care about connection broadcasts when you have something stored to be uploaded but can not upload it because of no data connection. When you have nothing to upload, don't waste processing and battery by keeping your receiver/service around. And when you do have emails waiting, then start up you broadcastreceiver, to know when you have data connection so that you can start uploading.
I do not think anyone is going to write a whole working solution for you, hopefully this is more than enough to get you on your way.
Edit:
Another thing you can do, is let the server allow acceptance of an array of your items, that way you can just upload it all at once when you get a valid connection. Generally you would do this if each item was decently small. But if you are uploading pictures or videos or anything large, best to do it one at a time probably.

Play sound when app is closed without hardcoded path to sound

I want to play my own custom notification sound to set my app apart from a system default sound. So, when I receive a GCM message, I have a function called generateNotification that puts a notification in the status bar and plays a sound.
Currently, I set the path to the sound like this:
String GENERAL_NOTIFICATION_SOUND = "android.resource://" + MyActivity.getInstance().getPackageName() + "/" + R.raw.sound_file;
This works when the app is open, even when the app is recently closed. But if the app is closed by Android's memory management, then MyActivity.getInstance() returns null, and my app crashes with a NullPointerException without properly displaying a notification because it couldn't resolve the path.
I believe I could just fix this by hardcoding the path, but I feel like there has to be a better way. How can you set a path to files that need to be accessed when the app might not be open?
First, you should not have a MyActivity.getInstance(), as that is a memory leak.
Second, whatever code is raising the Notification already has access to a Context, as that is where you get a NotificationManager from. getPackageName() is a method on Context. So, for example, your GCM IntentService is a Context, and so not only can it use getSystemService() to retrieve a NotificationManager, but it can call getPackageName() on itself to find out your app's package name.

How do I fake send SMS messages AND a system notification? Programmatical approach?

Update: To state this first: I'm looking for a programmatical way. I know it is easily possible with emulators, but I'm looking for a way to have it implemented in an actual application on my phone.
I've been playing around with this for a while now, although I can write messages to the inbox or outbox with
ContentValues values = new ContentValues();
values.put("address", "5551");
values.put("body", "the text of this message");
getContentResolver().insert(Uri.parse("content://sms/inbox"),values)
and of course
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
The WRITE_SMSis there just for some of the following, because with all the things I tried I could not get the system to receive a notification. I thought about investigating the code of the built-in SMS app but could not find it.
Here come the things I tried:
context.getContentResolver().notifyChange(Uri.parse("content://sms/inbox",null);
has just the same non-effect like:
Intent intent = new Intent("android.provider.Telephony.SMS_RECEIVED");
byte[] b = (byte[])(SmsMessage.getSubmitPdu("5551","5552","some_text",false).encodedMessage);
Object[] vrs = {b};
intent.putExtra("pdus",vrs);
sendBroadcast(intent);
As a workaround right now I'm calling the sms-list:
Intent intent = new Intent("android.intent.action.MAIN");
intent.setComponent(new ComponentName("com.android.mms","com.android.mms.ui.ConversationList"));
startActivity(intent);
Any ideas or hints?
Ok, so I have been browsing the android code, especially
http://www.java2s.com/Open-Source/Android/android-platform-apps/Mms/com/android/mms/transaction/MessagingNotification.java.htm
To my understanding all I'd need to do is call the public static MessagingNotification.blockingUpdateAllNotifications(context) after writing the SMS. Is there any way I can access this method?
Use the "emulator control" section in DDMS to send test sms/text to your emulator. You can also enter the fake number from which the sms is to be sent.
More information can be found under in the "Spoofing calls or SMS text messages" section of the Using DDMS document in the dev guide

Categories