I copy a source follow underlink
How to install Android apk from code in unity
but if I play in phone, it is show an error
Error:android.content.ActivityNotFoundException: No Activity found to handle Intent{act=android.intent.action.VIEW dat=content://com.mycompany.productname.fileprovider/files_root/files/data/ApkDownload.apk typ=applcation/vnd.android.package-archive flg=0x10000001}
Code:
public class AutoUpdateNew : MonoBehaviour {
public string downloadurl;
void Start()
{
StartCoroutine(downLoadFromServer());
}
IEnumerator downLoadFromServer()
{
//downloadurl = string url;
string url = "https://drive.google.com/uc?export=download&id=1SUqRAITK-8ezVA7t6ORuuS8X9f69ei8v";
string savePath = Path.Combine(Application.persistentDataPath, "data");
savePath = Path.Combine(savePath, "ApkDownload.apk");
Dictionary<string, string> header = new Dictionary<string, string>();
string userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36";
header.Add("User-Agent", userAgent);
WWW www = new WWW(url, null, header);
while (!www.isDone)
{
//Must yield below/wait for a frame
GameObject.Find("TextDebug").GetComponent<Text>().text = "Stat: " + www.progress;
yield return null;
}
byte[] yourBytes = www.bytes;
GameObject.Find("TextDebug").GetComponent<Text>().text = "Done downloading. Size: " + yourBytes.Length;
//Create Directory if it does not exist
if (!Directory.Exists(Path.GetDirectoryName(savePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
GameObject.Find("TextDebug").GetComponent<Text>().text = "Created Dir";
}
try
{
//Now Save it
System.IO.File.WriteAllBytes(savePath, yourBytes);
Debug.Log("Saved Data to: " + savePath.Replace("/", "\\"));
GameObject.Find("TextDebug").GetComponent<Text>().text = "Saved Data";
}
catch (Exception e)
{
Debug.LogWarning("Failed To Save Data to: " + savePath.Replace("/", "\\"));
Debug.LogWarning("Error: " + e.Message);
GameObject.Find("TextDebug").GetComponent<Text>().text = "Error Saving Data";
}
//Install APK
installApp(savePath);
}
/*
public bool installApp(string apkPath)
{
try
{
AndroidJavaClass intentObj = new AndroidJavaClass("android.content.Intent");
string ACTION_VIEW = intentObj.GetStatic<string>("ACTION_VIEW");
int FLAG_ACTIVITY_NEW_TASK = intentObj.GetStatic<int>("FLAG_ACTIVITY_NEW_TASK");
AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", ACTION_VIEW);
AndroidJavaObject fileObj = new AndroidJavaObject("java.io.File", apkPath);
AndroidJavaClass uriObj = new AndroidJavaClass("android.net.Uri");
AndroidJavaObject uri = uriObj.CallStatic<AndroidJavaObject>("fromFile", fileObj);
intent.Call<AndroidJavaObject>("setDataAndType", uri, "application/vnd.android.package-archive");
intent.Call<AndroidJavaObject>("addFlags", FLAG_ACTIVITY_NEW_TASK);
intent.Call<AndroidJavaObject>("setClassName","com.mycompany.productname","com.mycompany.productname.PackageInstallerActivity");
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
currentActivity.Call("startActivity", intent);
GameObject.Find("TextDebug").GetComponent<Text>().text = "Success";
return true;
}
catch (System.Exception e)
{
GameObject.Find("TextDebug").GetComponent<Text>().text = "Error: " + e.Message;
return false;
}
}*/
private bool installApp(string apkPath)
{
bool success = true;
GameObject.Find("TextDebug").GetComponent<Text>().text = "Installing App";
try
{
//Get Activity then Context
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject unityContext = currentActivity.Call<AndroidJavaObject>("getApplicationContext");
//Get the package Name
string packageName = unityContext.Call<string>("getPackageName");
string authority = packageName + ".fileprovider";
AndroidJavaClass intentObj = new AndroidJavaClass("android.content.Intent");
string ACTION_VIEW = intentObj.GetStatic<string>("ACTION_VIEW");
AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", ACTION_VIEW);
int FLAG_ACTIVITY_NEW_TASK = intentObj.GetStatic<int>("FLAG_ACTIVITY_NEW_TASK");
int FLAG_GRANT_READ_URI_PERMISSION = intentObj.GetStatic<int>("FLAG_GRANT_READ_URI_PERMISSION");
//File fileObj = new File(String pathname);
AndroidJavaObject fileObj = new AndroidJavaObject("java.io.File", apkPath);
//FileProvider object that will be used to call it static function
AndroidJavaClass fileProvider = new AndroidJavaClass("android.support.v4.content.FileProvider");
//getUriForFile(Context context, String authority, File file)
AndroidJavaObject uri = fileProvider.CallStatic<AndroidJavaObject>("getUriForFile", unityContext, authority, fileObj);
intent.Call<AndroidJavaObject>("setDataAndType", uri, "application/vnd.android.package-archive");
intent.Call<AndroidJavaObject>("addFlags", FLAG_ACTIVITY_NEW_TASK);
intent.Call<AndroidJavaObject>("addFlags", FLAG_GRANT_READ_URI_PERMISSION);
currentActivity.Call("startActivity", intent);
GameObject.Find("TextDebug").GetComponent<Text>().text = "Success";
}
catch (System.Exception e)
{
GameObject.Find("TextDebug").GetComponent<Text>().text = "Error: " + e.Message;
success = false;
}
return success;
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mycompany.productname" xmlns:tools="http://schemas.android.com/tools"
android:installLocation="preferExternal" android:versionName="1.0" android:versionCode="1">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="#style/UnityThemeSelector" android:icon="#drawable/app_icon" android:label="#string/app_name" android:debuggable="true">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.success.apkupdateTest.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
<activity android:name=".PackageInstallerActivity">
</activity>
</application>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
</manifest>
In the link you mentioned in your question, the author said:
For Android API 24 and above, this requires a different code since
the API changed.
So you have to check the version of your device using methods like this and then call the appropriate function.
Related
I have an NFC TAG scanner application which works fine and scans the tag and i can also read and write into tags without any issues , the only issue is that when i change the app package name and start the code , the nfc no longer works and scans tags , but when i revert to the other package name it works fine , any reason why and what could be wrong , Thank you in advance
class ActivateActivity : AppCompatActivity() {
private lateinit var binding : ActivityActivateScreenBinding
lateinit var writeTagFilters: Array<IntentFilter>
var nfcAdapter: NfcAdapter? = null
var pendingIntent: PendingIntent? = null
var writeMode = false
var myTag: Tag? = null
var actualMsg = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityActivateScreenBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnActivate.setOnClickListener {
val organizationId = binding.organizationIdEdit.text.toString()
val nfcMsg = binding.txtNFCMessage.text.toString()
actualMsg = DOMAIN + organizationId + ucync + nfcMsg
try {
if(myTag == null){
Toast.makeText(this, ERROR_DETECTED,Toast.LENGTH_LONG).show()
} else {
write(actualMsg,myTag)
Toast.makeText(this, WRITE_SUCCESS,Toast.LENGTH_LONG).show()
}
}
catch (e : IOException){
Toast.makeText(this, WRITE_ERROR, Toast.LENGTH_LONG).show()
e.printStackTrace()
}
catch (e: FormatException){
Toast.makeText(this, WRITE_ERROR, Toast.LENGTH_LONG).show()
e.printStackTrace()
}
}
nfcAdapter = NfcAdapter.getDefaultAdapter(this)
if (nfcAdapter == null) {
// Stop here, we definitely need NFC
Toast.makeText(this, "This device doesn't support NFC.", Toast.LENGTH_LONG).show()
finish()
}
//For when the activity is launched by the intent-filter for android.nfc.action.NDEF_DISCOVERE
readFromIntent(intent)
pendingIntent = PendingIntent.getActivity(this, 0, Intent(this, javaClass)
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
PendingIntent.FLAG_IMMUTABLE)
val tagDetected = IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
tagDetected.addCategory(Intent.CATEGORY_DEFAULT)
writeTagFilters = arrayOf(tagDetected)
}
/******************************************************************************
* Read From NFC Tag
****************************************************************************/
private fun readFromIntent(intent: Intent) {
val action = intent.action
if (NfcAdapter.ACTION_TAG_DISCOVERED == action || NfcAdapter.ACTION_TECH_DISCOVERED == action || NfcAdapter.ACTION_NDEF_DISCOVERED == action) {
myTag = intent.getParcelableExtra<Parcelable>(NfcAdapter.EXTRA_TAG) as Tag?
val rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
val msgs = mutableListOf<NdefMessage>()
if (rawMsgs != null) {
for (i in rawMsgs.indices) {
msgs.add(i, rawMsgs[i] as NdefMessage)
}
buildTagViews(msgs.toTypedArray())
}
}
}
private fun buildTagViews(msgs: Array<NdefMessage>) {
if (msgs.isEmpty()) return
val text: String
val payload = msgs[0].records[0].payload
val textEncoding: Charset = if ((payload[0] and 128.toByte()).toInt() == 0) Charsets.UTF_8 else Charsets.UTF_16 // Get the Text Encoding
val languageCodeLength: Int = (payload[0] and 51).toInt() // Get the Language Code, e.g. "en"
try {
// Get the Text
text = String(payload, languageCodeLength + 1, payload.size - languageCodeLength - 1, textEncoding)
Log.d("VALUE","VALUE IS " + text)
} catch (e: UnsupportedEncodingException) {
Log.e("UnsupportedEncoding", e.toString())
}
}
/******************************************************************************
* Write to NFC Tag
****************************************************************************/
private fun write(msg : String , tag : Tag?){
val records = arrayOf(createRecord(msg))
val message = NdefMessage(records)
// Get an instance of Ndef for the tag.
val ndef = Ndef.get(tag)
// Enable I/O
ndef.connect()
// Write the message
ndef.writeNdefMessage(message)
// Close the connection
ndef.close()
}
#Throws(UnsupportedEncodingException::class)
private fun createRecord(text: String): NdefRecord {
val lang = "en"
val textBytes = text.toByteArray()
val langBytes = lang.toByteArray(charset("US-ASCII"))
val langLength = langBytes.size
val textLength = textBytes.size
val payload = ByteArray(1 + langLength + textLength)
// set status byte (see NDEF spec for actual bits)
payload[0] = langLength.toByte()
// copy langbytes and textbytes into payload
System.arraycopy(langBytes, 0, payload, 1, langLength)
System.arraycopy(textBytes, 0, payload, 1 + langLength, textLength)
return NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, ByteArray(0), payload)
}
/**
* For reading the NFC when the app is already launched
*/
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
readFromIntent(intent)
if (NfcAdapter.ACTION_TAG_DISCOVERED == intent.action) {
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
}
}
public override fun onPause() {
super.onPause()
writeModeOff()
}
public override fun onResume() {
super.onResume()
writeModeOn()
}
/******************************************************************************
* Enable Write and foreground dispatch to prevent intent-filter to launch the app again
****************************************************************************/
private fun writeModeOn() {
writeMode = true
nfcAdapter!!.enableForegroundDispatch(this, pendingIntent, writeTagFilters, null)
}
/******************************************************************************
* Disable Write and foreground dispatch to allow intent-filter to launch the app
****************************************************************************/
private fun writeModeOff() {
writeMode = false
nfcAdapter!!.disableForegroundDispatch(this)
}
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.NFC"/>
<uses-feature android:name="android.hardware.nfc"
android:required="true"/>
<application
android:name=".BaseApplication"
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.UcyncBusiness"
tools:targetApi="31">
<activity
android:name=".ui.ActivateActivity"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".ui.HomeActivity"
android:exported="false">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".ui.SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity android:name=".MainActivity" />
</application>
I have some issues developing the nfc plugin in Unity.
When nfc tagging, onNewIntent is not called, the app moves to the background and the default nfc tagviewer opens.
It worked on Android 9 and below, but not android 10.
I found a suspicious logs using Logcat.
NfcService: setForegroundDispatch: Caller not in foreground.
2020-04-05 15:33:45.857 32411-32411/? E/class com.package.product.NFCPlugin: call Activity
2020-04-05 15:33:45.857 32411-32411/? E/class com.package.product.NFCPlugin: intent:Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp= com.package.product/.NFCPlugin bnds=[1131,670][1405,1123] (has extras) }
2020-04-05 15:33:45.857 32411-32411/? E/class com.package.product.NFCPlugin: Skill Launcher Cat: LAUNCHER
2020-04-05 15:33:45.858 32411-32411/? E/class com.package.product.NFCPlugin: onResume Activity
2020-04-05 15:33:45.858 32411-32411/? E/class com.package.product.NFCPlugin: Call Check ForegroundDispatch
2020-04-05 15:33:45.858 7904-7904/? I/[LGHome6]Launcher: rebindModel: rebind = false, flag = 0, currentPage = 4, isLandscape = true, mChangedProfileByMultiWindow = false, mOrientationOfCurrentLayout = 0, mWorkspaceLoading = false, mChangedProfile = true, mIsMirrorMode = false
2020-04-05 15:33:45.858 7506-7542/? E/NfcService: setForegroundDispatch: Caller not in foreground.
2020-04-05 15:33:45.859 32411-32735/? W/System.err: javax.net.ssl.SSLException: Write error: ssl=0x7c105b0c48: I/O error during system call, Broken pipe
2020-04-05 15:33:45.859 32411-32411/? E/class com.package.product.NFCPlugin: Equal Result:true
2020-04-05 15:33:45.860 2437-2462/? V/DesktopModeManager: Notification is not exist.
2020-04-05 15:33:45.860 5005-5005/? I/OpaLayout: Setting opa enabled to true
2020-04-05 15:33:45.863 2437-8224/? D/InputDispatcher: Window went away: Window{f88f9f9 u0 com.lge.launcher3/com.lge.launcher3.LauncherExtension}
I have found several places to print the log. As a result, I found the part that outputs the same log in Android Code Search.
https://cs.android.com/android/platform/superproject/+/master:packages/apps/Nfc/src/com/android/nfc/NfcService.java;l=1053;bpv=1;bpt=1?q=NfcService:%20setForegroundDispatch%20enable&ss=android%2Fplatform%2Fsuperproject
#Override
public void setForegroundDispatch(PendingIntent intent,
IntentFilter[] filters, TechListParcel techListsParcel)
{
NfcPermissions.enforceUserPermissions(mContext);
if (!mForegroundUtils.isInForeground(Binder.getCallingUid()))
{
Log.e(TAG, "setForegroundDispatch: Caller not in foreground.");
return;
}
// Short-cut the disable path
if (intent == null && filters == null && techListsParcel == null)
{
mNfcDispatcher.setForegroundDispatch(null, null, null);
return;
}
// Validate the IntentFilters
if (filters != null) {
if (filters.length == 0) {
filters = null;
} else {
for (IntentFilter filter : filters) {
if (filter == null) {
throw new IllegalArgumentException("null IntentFilter");
}
}
}
}
// Validate the tech lists
String[][] techLists = null;
if (techListsParcel != null) {
techLists = techListsParcel.getTechLists();
}
mNfcDispatcher.setForegroundDispatch(intent, filters, techLists);
}
According to the code, if a log occurs, processing is stopped without returning any results. So it seems that the foregroundDispatch does not proceed and goes over.
I've been trying for a long time to solve this issue, but couldn't find the same case, so I think it's a new issue in android 10.
Does anyone know how to fix this?
Lastly, I'm sorry that it was difficult to understand because I used a translation site to write this question.
Below is the code for the plugin.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
m_instance=this;
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter == null)
{
finish();
return;
}
pendingIntent = PendingIntent.getActivity(NFCPlugin.this, 0, new Intent(NFCPlugin.this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter _ndfFilter = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
try
{
_ndfFilter.addDataType("*/*");
}
catch (MalformedMimeTypeException e) {
throw new RuntimeException("Filter fail:", e);
}
IntentFilter _ndfFilter_NDEF = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
_ndfFilter_NDEF.addDataType("*/*");
}
catch (MalformedMimeTypeException e) {
throw new RuntimeException("Filter fail:", e);
}
IntentFilter _ndfFilter_Tech = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
try {
_ndfFilter_Tech.addDataType("*/*");
}
catch (MalformedMimeTypeException e) {
throw new RuntimeException("Filter fail:", e);
}
mIntentFilter = new IntentFilter[] { _ndfFilter ,_ndfFilter_NDEF,_ndfFilter_Tech};
techListsArray = new String[][] {
new String[] {NFCPlugin.class.getName()},
new String[] {TagTechnology.class.getName()},
new String[] {NfcA.class.getName()},
new String[] {NfcB.class.getName()},
new String[] {NfcV.class.getName()},
new String[] {IsoDep.class.getName()},
new String[] {Ndef.class.getName()},
new String[] {NdefFormatable.class.getName()}
};
}
#Override
public void onResume() {
super.onResume();
Log.e(NFCPlugin.class.toString(), "onResume Activity");
mNfcAdapter.enableForegroundDispatch(this, pendingIntent, mIntentFilter, techListsArray);
}
#Override
public void onPause() {
super.onPause();
Log.e(NFCPlugin.class.toString(), "onPause Activity");
mNfcAdapter.disableForegroundDispatch(this);
}
Next is the manifest content.
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.package.product"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="preferExternal">
<uses-permission android:name="android.permission.NFC" >
</uses-permission>
<uses-feature
android:name="android.hardware.nfc"
android:required="true" >
</uses-feature>
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"/>
<application
android:theme="#style/UnityThemeSelector"
android:icon="#mipmap/app_icon"
android:label="#string/app_name"
android:networkSecurityConfig="#xml/network_security_config"
>
<activity android:name=".NFCPlugin"
android:launchMode="singleTask"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:screenOrientation="landscape"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/tech_list" />
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
</manifest>
lastly, it is the contents of techList required for TECH_DISCOVERED.
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.NfcF</tech>
<tech>android.nfc.tech.NfcV</tech>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.NdefFormatable</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>
Hi i am trying to open a camera and i saw the documentation of android on how to use it.
so i just copy paste it to my code, and i already set the permission of it, but when i am clicking the button, the camera is not opening.
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
if(requestCode == CAMERA_REQUEST_CODE){
Log.d("ano_code",Integer.toString(requestCode));
if(resultCode == Activity.RESULT_OK){
File file = new File(currentPhotoPath);
selectedImage.setImageURI(Uri.fromFile(file));
}else{
Log.d("mali","mali nga");
}
}
if(requestCode == GALLERY_REQUEST_CODE){
if(resultCode == Activity.RESULT_OK){
Uri contentUri = data.getData();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp +"."+getFileExt(contentUri);
Log.d("tag", "onActivityResult: Gallery Image Uri: " + imageFileName);
selectedImage.setImageURI(contentUri);
}
}
}
private String getFileExt(Uri contentUri) {
ContentResolver c = getContentResolver();
MimeTypeMap mime = MimeTypeMap.getSingleton();
return mime.getExtensionFromMimeType(c.getType(contentUri));
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
//File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
}
// Continue only if the File was successfully created
if (photoFile != null) {
Log.d("qqqqq","dito na ao4");
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.test.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}
}
}
Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera" android:required="true"/>
<!--This should have the Activity files ONLY-->
<application
android:hardwareAccelerated="false"
android:largeHeap="true"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme.NoActionBar">
<activity
android:name=".Utilities.SplashScreen"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.test.android.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data>
</provider>
</application>
</manifest>
i really don't know what to do, there is no error, does anyone encounter this too?
here is the link of the documentation.
https://developer.android.com/training/camera/photobasics
can u declare provider in manifest? yes then paste error message from logcat.
this thing is behaving very strange with us. Some devices hit onmsgrcv, while others dont when the app is closed. How come apps like Whatsapp receives notification when they are closed? Why dont I receive when my app is closed? Need help...
alert.php
$divisions = $_GET['divisions'];
$tokens = array();
$tokens[0] = "e3-nlNImIR8:APA91bGQ3WJW_jWfelz5mEp6L6--wNgdZtb93Bx7kZBSsXUaGYOvdg0_RaP7KlnlfGBD4Xqs3Kyr-IKc0s3072DPGCvToeFeO0w9EHazGOqZt30KbNE7zQr4gbklJ9nZlypyU8IyYzIl";
$tokens[1] = "fWFN3lpvIjI:APA91bF1Kkh-EBEEi8-qkrBgtwxzFAK4WfupWvgjA1PlWjquKTg8yUzMALO9UeTBJHw8UMbE_SLM2cObpf_PolQNkg4AW10Dsg7rtwvI41tIL83Kpm8BZ8cs4GEGXOYrbF0KaB_GG3jo";
$tokens[2] = "eimGs3j1bsA:APA91bFhJHRtxTKldSsrIVr8d12fVLId1DYkUIKgiczTrXGgKLQnoud9ZMIvi1wKHHQWkGcV2ptmLqLfHywgIwWzRxpfaJuICNvgqF2OUnfKist3_t-2XuASukuc4_6Ua9sER29c-oi9";
$data = array(
"divisions" => $divisions
);
$fields = array(
'to' => "/topics/ALERT",
'data' => $data
);
$headers = array(
'Authorization:key = AAAAjCAUSaQ:APA91bGa0FsAjY-5tjEBIiavo960rU39UmendbRC-akMdKxJIdSsqwwlNl4YMl1iAIYd2evyp_5kWe6l_RmpzLGXHiY91NY8LRKa75XNruD9Jvnyu8xNA2IIinLlkJLi8TL5Ud4M9hjY',
'Content-Type: application/json'
);
$ch = curl_init();
$url = "https://fcm.googleapis.com/fcm/send";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch, CURLOPT_POSTFIELDS,json_encode($fields));
$result = curl_exec($ch);
echo $result;
curl_close($ch);
?>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
<!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
<uses-feature android:name="android.hardware.location.gps" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:hardwareAccelerated="false"
android:largeHeap="true"
android:label="#string/app_name"
android:roundIcon="#drawable/ic_launcher"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:name="android.support.multidex.MultiDexApplication"
>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_launcher" />
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
<activity
android:name="com.kayhanswarup.avtro.prokriti.ui.HomeActivity"
android:configChanges="locale|orientation"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
</activity>
<!-- <service android:name=".services.MyService" android:process=":my_service" /> -->
<service android:name="com.kayhanswarup.avtro.prokriti.services.CloudMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name="com.kayhanswarup.avtro.prokriti.services.InstanceTokenService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<provider android:authorities="com.facebook.app.FacebookContentProvider1697853730520523"
android:name="com.facebook.FacebookContentProvider"
android:exported="true"/>
<meta-data android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id"/>
<activity android:name="com.kayhanswarup.avtro.prokriti.ui.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="#string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="#string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
</application>
CloudMessagingService.java
public class CloudMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if (remoteMessage.getData().size() > 0) {
ML.d("Message data exists. Should go background: " + remoteMessage.getData());
goBackend(remoteMessage.getData().get("divisions"));
}
else if (remoteMessage.getNotification() != null) {
ML.d("Message Notification Body: " + remoteMessage.getNotification().getBody());
sendNotification(remoteMessage.getNotification().getBody());
}
}
public int currentDivisionIndex = -1;
public String currentDivision="";
private void goBackend(final String messageBody){
ML.setTagServer(true);
ML.i("Reached with data: "+messageBody);
final Intent intent1 = new Intent(this,HomeActivity.class);
final String[] divisions = ApiEndPoints.DIVISIONS;
try {
provider = LocationManager.NETWORK_PROVIDER;
locationManager=(LocationManager)getBaseContext().getSystemService(Context.LOCATION_SERVICE);
final Location location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if(location!=null){
ML.d("location(lng,lat) value in background app: "+location.getLongitude()+","+location.getLatitude());
ApiClient.getInstance(getBaseContext())
.getWeather(location.getLatitude()+"", location.getLongitude()+"", new OnResponse<Weather, ANError>() {
#Override
public void onResponse(Weather response) {
try{
currentDivision= response.getQuery().getResults().getChannel().getLocation()
.getRegion();
}catch (Exception e){
ML.e("Exception during api client weather: "+e.getMessage());
return;
}
ML.d("Current DIVISION: "+currentDivision);
if(currentDivision!=null&¤tDivision.length()>=3){
ML.d("current Division is: "+currentDivision);
for(int i=0;i<divisions.length;i++){
ML.i("No#"+i+" division: "+divisions[i]);
if((currentDivision.toLowerCase().contains(divisions[i].toLowerCase()))||divisions[i].toLowerCase().contains(currentDivision.toLowerCase())){
ML.d("We got a match: "+i);
currentDivisionIndex = i;
}else{
ML.d("Current division: "+currentDivision.toLowerCase());
ML.d("INDEX DIVISION: "+divisions[i].toLowerCase());
}
}
ML.d("Current: "+currentDivisionIndex);
if(currentDivisionIndex<0||(currentDivisionIndex>=0&&messageBody.substring(currentDivisionIndex,currentDivisionIndex+1).equals("0"))){
ML.d("Returning from background" +
"DONE");
ML.d("Reached background but location mismatched");
if(currentDivisionIndex>=0){
ML.d("What is this: "+messageBody.substring(currentDivisionIndex,currentDivisionIndex+1));
}
return;
}else{
ML.d("Atleast found sth...");
}
ML.d("VALUE ACCORDING TO : "+messageBody.substring(currentDivisionIndex,currentDivisionIndex+1));
int val=0;
try {
val= Integer.parseInt(messageBody.substring(currentDivisionIndex,currentDivisionIndex+1));
} catch (Exception e) {
ML.e("Integer parsing error: "+e.getMessage());
}
if(currentDivisionIndex>=0&&val!=0){
String lang = "en";
try {
lang = isLangBangla()?"bn":"en";
} catch (Exception e) {
ML.e("GOT EXCEPTION");
lang="bn";
}
FirebaseDatabase.getInstance().getReference("versions")
.child("001")
.child("locales")
.child(lang)
.child("alert")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ML.d("Will show an alert... IF LUCKY...");
final Alert alert = dataSnapshot.getValue(Alert.class);
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("versions").child("001")
.child("LOG");
String key = ref.push().getKey();
ref.child(key).setValue(ML.getLog() + "", new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if(databaseError==null)
Log.d("Prokriti","sent");
ML.setTagServer(false);
Notify.getInstance().setHasNotification(true);
String title = getString(R.string.alert_title);
String body = getString(R.string.alert_body);
try {
if(alert!=null){
ML.d("Alert: "+alert.toString());
title = alert.getTitle();
body = alert.getBody();
}else ML.e("Alert is null");
} catch (Exception e) {
ML.e("no alert found"+e.getMessage());
}
try {
Notify.getInstance().setTitle(title);
Notify.getInstance().setDescription(body);
} catch (Exception e) {
ML.e("Notify error: "+e.getMessage());
Notify.getInstance().setTitle("Title");
Notify.getInstance().setDescription("Danger");
}
PendingIntent pendingIntent = PendingIntent.getActivity(CloudMessagingService.this, 0 /* Request code */, intent1,
PendingIntent.FLAG_UPDATE_CURRENT);
ML.d("Pack res path: "+getPackageResourcePath());
ML.d("Pack res: "+getPackageName());
Uri defaultSoundUri= Uri.parse("android.resource://"+getPackageName()+"/"+ R.raw.alert);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(CloudMessagingService.this)
.setSmallIcon(R.drawable.ic_cloud)
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
});
// intent.putExtra("locale","notify");
}
#Override
public void onCancelled(DatabaseError databaseError) {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("versions").child("001")
.child("LOG");
String key = ref.push().getKey();
ref.child(key).setValue(ML.getLog() + "", new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if(databaseError==null)
Log.d("Prokriti","sent");
ML.setTagServer(false);
}
});
}
});
}
}
}
#Override
public void onError(ANError error) {
ML.e("Error: "+error.getMessage());
}
});
}
} catch (Exception e) {
ML.e("Still shows fucking ERROR: "+e.getMessage());
}
}
public static boolean isLangBangla(){
return LocaleManager.getInstance().getLocale().getDisplayLanguage().toLowerCase().contains("bengali");
}
LocationManager locationManager=null;
String provider;
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// provider = LocationManager.NETWORK_PROVIDER;
// locationManager=(LocationManager)getBaseContext().getSystemService(Context.LOCATION_SERVICE);
Location location = locationManager.getLastKnownLocation(provider);
if(location!=null){
ML.d("location(lng,lat): "+location.getLongitude()+","+location.getLatitude());
}else ML.d("location is null...");
intent.putExtra("locale","notify");
Notify.getInstance().setHasNotification(true);
Notify.getInstance().setTitle("Title");
Notify.getInstance().setDescription("ED");
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
ML.d("Pack res path: "+getPackageResourcePath());
ML.d("Pack res: "+getPackageName());
Uri defaultSoundUri= Uri.parse("android.resource://"+getPackageName()+"/"+ R.raw.alert);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_cloud)
.setContentTitle(getString(R.string.alert_title))
.setContentText(getString(R.string.alert_body))
.setAutoCancel(false)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
LocationListener locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
}
I created an app which is a Book Shelf, because I borrow books very often, I use BroadcastReceiver to send notifications when the screen is on. But, the BroadcastReceiver works only if the app is opened (the notification don't show when it's closed).
MyReceiver.java
public class MyReceiver extends BroadcastReceiver
{
public static final int ID_NOTFICATION_REMINDER = 0;
SharedPreferences sp = MainActivity.sp;
SharedPreferences.Editor edit = MainActivity.edit;
private NotificationManager mNotificationManager;
#SuppressWarnings("deprecation")
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().matches("android.intent.action.SCREEN_ON"))
{
for (int i = 0; i < sp.getInt("count", 0); i++)
{
mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
String name = sp.getString("name" + i, "NULL");
String owners = sp.getString("owner" + i, "NULL");
String holder = sp.getString("where" + i, "NULL");
String date = sp.getString("date" + i, "NULL");
SimpleDateFormat dfDate = new SimpleDateFormat(
"dd-MM-yyyy");
Calendar c = Calendar.getInstance();
String currentDate = dfDate.format(c.getTime());
if ((!owners.equals(holder)) && (!name.isEmpty()) && (Utils.monthDiff(date, currentDate) >= 30))
{
int icon = R.drawable.book_shelf_icon;
CharSequence tickerText = "A message from Book Shelf";
long when = System.currentTimeMillis();
final Notification mNotification = new Notification(icon, tickerText, when);
String contentTitle = "The book "+name+" hasn't changed it's state for over a month!";
String contentText = "Tap to open Book Shelf";
Intent mIntent = new Intent(context, MainActivity.class);
PendingIntent mPendingIntent = PendingIntent.getActivity(context, 0, mIntent, 0);
mNotification.setLatestEventInfo(context, contentTitle, contentText, mPendingIntent);
mNotificationManager.notify(ID_NOTFICATION_REMINDER, mNotification);
}
}
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.asaf.applications.bookshelf"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
<application
android:allowBackup="true"
android:icon="#drawable/book_shelf_icon"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.asaf.applications.bookshelf.MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name="com.asaf.applications.bookshelf.MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SCREEN_ON" />
</intent-filter>
</receiver>
</application>
</manifest>
You are getting a reference to the SharedPreferences from the MainActivity
SharedPreferences sp = MainActivity.sp;
However when the activity isn't running, you will be getting a NPE (of sp =null )
A Broadacast reciever already has access to the context so use that to accuire a reference to the SharedPreferences
#SuppressWarnings("deprecation")
public void onReceive(Context context, Intent intent)
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
/*
* Your code
*/
}