मुझे यह जानने में दिलचस्पी है कि क्या यह संभव है कि एक कस्टम एंड्रॉइड एप्लिकेशन से डायनामिक रूप से डाउनलोड किया गया एपीके इंस्टॉल किया जाए।
मुझे यह जानने में दिलचस्पी है कि क्या यह संभव है कि एक कस्टम एंड्रॉइड एप्लिकेशन से डायनामिक रूप से डाउनलोड किया गया एपीके इंस्टॉल किया जाए।
जवाबों:
आप आसानी से एक प्ले स्टोर लिंक या एक इंस्टेंट इंस्टाल लॉन्च कर सकते हैं:
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.parse("content:///path/to/your.apk"),
"application/vnd.android.package-archive");
startActivity(promptInstall);
या
Intent goToMarket = new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse("https://play.google.com/store/apps/details?id=com.package.name"));
startActivity(goToMarket);
हालाँकि, आप उपयोगकर्ता की स्पष्ट अनुमति के बिना .apks स्थापित नहीं कर सकते हैं ; जब तक डिवाइस और आपका प्रोग्राम रूट नहीं होता है।
/sdcard
, क्योंकि यह एंड्रॉइड 2.2+ और अन्य उपकरणों पर गलत है। Environment.getExternalStorageDirectory()
इसके बजाय उपयोग करें ।
File file = new File(dir, "App.apk");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);
मुझे एक ही समस्या थी और कई प्रयासों के बाद, इसने मेरे लिए इस तरह से काम किया। मुझे पता नहीं क्यों, लेकिन डेटा सेट करना और अलग से मेरे इरादे को खराब कर दिया।
setData()
प्रकार पैरामीटर को हटा दिया जाएगा। setDataAndType()
यदि आप दोनों के लिए मान देना चाहते हैं तो आप अवश्य उपयोग करें । यहाँ: developer.android.com/reference/android/content/…
इस प्रश्न के समाधान targetSdkVersion
23 और नीचे के सभी पर लागू होते हैं। Android N के लिए, यानी API स्तर 24 और इसके बाद के संस्करण, हालांकि, वे निम्न अपवाद के साथ काम और दुर्घटना नहीं करते हैं:
android.os.FileUriExposedException: file:///storage/emulated/0/... exposed beyond app through Intent.getData()
यह इस तथ्य के कारण है कि एंड्रॉइड 24 से शुरू होकर, Uri
डाउनलोड की गई फ़ाइल को संबोधित करने के लिए बदल गया है। उदाहरण के लिए, appName.apk
पैकेज नाम के साथ ऐप की प्राथमिक बाहरी फ़ाइल सिस्टम पर संग्रहीत एक इंस्टॉलेशन फ़ाइल इस प्रकार com.example.test
होगी
file:///storage/emulated/0/Android/data/com.example.test/files/appName.apk
के लिए API 23
और नीचे है, जबकि कुछ ऐसा
content://com.example.test.authorityStr/pathName/Android/data/com.example.test/files/appName.apk
के लिये API 24
और ऊपर।
इस पर अधिक जानकारी मिल सकती है यहां है और मैं इससे गुजरने वाला नहीं हूं।
के लिए प्रश्न का उत्तर देने targetSdkVersion
के24
लिए और इसके बाद के संस्करण, एक निम्न चरणों का पालन करने के लिए है: AndroidManifest.xml करने के लिए निम्न करें:
<application
android:allowBackup="true"
android:label="@string/app_name">
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.authorityStr"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths"/>
</provider>
</application>
2. निम्न paths.xml
फ़ाइल को xml
फ़ोल्डर में जोड़ेंres
src, main में :
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="pathName"
path="pathValue"/>
</paths>
pathName
है कि ऊपर अनुकरणीय सामग्री उरई उदाहरण में दिखाया गया है और pathValue
सिस्टम पर वास्तविक पथ है। यह एक अच्छा विचार होगा ""। (बिना उद्धरण के) ऊपर दिए गए pathValue के लिए यदि आप कोई अतिरिक्त उपनिर्देशिका नहीं जोड़ना चाहते हैं।
appName.apk
प्राथमिक बाहरी फाइल सिस्टम पर नाम के साथ एपीके को स्थापित करने के लिए निम्नलिखित कोड लिखें :
File directory = context.getExternalFilesDir(null);
File file = new File(directory, fileName);
Uri fileUri = Uri.fromFile(file);
if (Build.VERSION.SDK_INT >= 24) {
fileUri = FileProvider.getUriForFile(context, context.getPackageName(),
file);
}
Intent intent = new Intent(Intent.ACTION_VIEW, fileUri);
intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
intent.setDataAndType(fileUri, "application/vnd.android" + ".package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
activity.finish();
बाहरी फ़ाइल सिस्टम पर अपने स्वयं के ऐप की निजी निर्देशिका में लिखते समय कोई अनुमति भी आवश्यक नहीं है।
मैंने यहाँ एक AutoUpdate लाइब्रेरी लिखी है जिसमें मैंने ऊपर प्रयोग किया है।
.authorityStr
बाद context.getPackageName()
काम करना चाहिए।
खैर, मैंने गहराई से खुदाई की, और Android स्रोत से PackageInstaller एप्लिकेशन के स्रोत मिले।
https://github.com/android/platform_packages_apps_packageinstaller
प्रकट से मैंने पाया कि इसे अनुमति की आवश्यकता है:
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
और स्थापना की वास्तविक प्रक्रिया पुष्टि के बाद होती है
Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
newIntent.setClass(this, InstallAppProgress.class);
String installerPackageName = getIntent().getStringExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME);
if (installerPackageName != null) {
newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);
}
startActivity(newIntent);
मैं सिर्फ इस तथ्य को साझा करना चाहता हूं कि मेरी एपीके फाइल मेरे ऐप "डेटा" डायरेक्टरी में सेव हो गई थी और मुझे उस तरह से इंस्टॉल करने की अनुमति देने के लिए एपीके फाइल पर अनुमतियों को बदलने के लिए दुनिया को पठनीय बनाने की जरूरत थी, अन्यथा "पार्स त्रुटि:" पैकेज को पार्स करने में समस्या है "फेंक रहा था; इसलिए @Horaceman से समाधान का उपयोग करता है:
File file = new File(dir, "App.apk");
file.setReadable(true, false);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);
यह दूसरों की बहुत मदद कर सकता है!
प्रथम:
private static final String APP_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyAppFolderInStorage/";
private void install() {
File file = new File(APP_DIR + fileName);
if (file.exists()) {
Intent intent = new Intent(Intent.ACTION_VIEW);
String type = "application/vnd.android.package-archive";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri downloadedApk = FileProvider.getUriForFile(getContext(), "ir.greencode", file);
intent.setDataAndType(downloadedApk, type);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
intent.setDataAndType(Uri.fromFile(file), type);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
getContext().startActivity(intent);
} else {
Toast.makeText(getContext(), "ّFile not found!", Toast.LENGTH_SHORT).show();
}
}
दूसरा: एंड्रॉइड 7 और इसके बाद के संस्करण के लिए आपको नीचे की तरह एक प्रदाता को परिभाषित करना चाहिए!
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="ir.greencode"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths" />
</provider>
तीसरा: Res / xml फ़ोल्डर में path.xml को नीचे की तरह परिभाषित करें! मैं आंतरिक भंडारण के लिए इस पथ का उपयोग कर रहा हूँ यदि आप इसे किसी और चीज़ में बदलना चाहते हैं तो कुछ तरीका है! आप इस लिंक पर जा सकते हैं: FileProvider
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="your_folder_name" path="MyAppFolderInStorage/"/>
</paths>
फोर्थ: आपको इस अनुमति को प्रकट में जोड़ना चाहिए:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
एप्लिकेशन को पैकेज स्थापित करने का अनुरोध करने देता है। 25 से अधिक API को लक्षित करने वाले ऐप्स को Intent.ACTION_INSTALL_PACKAGE का उपयोग करने के लिए यह अनुमति होनी चाहिए।
कृपया सुनिश्चित करें कि प्रदाता प्राधिकरण समान हैं!
हाँ, यह मुमकिन है। लेकिन इसके लिए आपको असत्यापित स्रोतों को स्थापित करने के लिए फोन की आवश्यकता होगी। उदाहरण के लिए, SlideMe ऐसा करता है। मुझे लगता है कि सबसे अच्छी बात यह है कि आप यह देख सकते हैं कि क्या एप्लिकेशन मौजूद है और एंड्रॉइड मार्केट के लिए एक इरादा भेजें। आपको Android Market के लिए कुछ url योजना का उपयोग करना चाहिए।
market://details?id=package.name
मुझे ठीक से पता नहीं है कि गतिविधि कैसे शुरू की जाए, लेकिन यदि आप उस तरह के यूआरएल के साथ गतिविधि शुरू करते हैं। इसे एंड्रॉइड मार्केट खोलना चाहिए और आपको ऐप्स इंस्टॉल करने का विकल्प देना चाहिए।
यह ध्यान देने योग्य है कि यदि आप DownloadManager
अपने डाउनलोड को बंद करने के लिए उपयोग करते हैं , तो इसे किसी बाहरी स्थान पर सहेजना सुनिश्चित करें जैसे setDestinationInExternalFilesDir(c, null, "<your name here>).apk";
। पैकेज-आर्काइव प्रकार के साथ आशय content:
आंतरिक स्थान पर डाउनलोड के साथ उपयोग की जाने वाली योजना को पसंद नहीं करता है , लेकिन पसंद करता है file:
। (आंतरिक पथ को फ़ाइल ऑब्जेक्ट में लपेटने का प्रयास करना और फिर पथ प्राप्त करना या तो काम नहीं करता है, भले ही यह एक परिणाम के रूप में होfile:
यूआरएल , क्योंकि ऐप एपीके को पार्स नहीं करेगा; ऐसा लगता है कि यह बाहरी होना चाहिए।)
उदाहरण:
int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String downloadedPackageUriString = cursor.getString(uriIndex);
File mFile = new File(Uri.parse(downloadedPackageUriString).getPath());
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.fromFile(mFile), "application/vnd.android.package-archive")
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
appContext.startActivity(promptInstall);
अनुमति का अनुरोध करने के लिए मत भूलना:
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
android.Manifest.permission.READ_EXTERNAL_STORAGE
प्रदाता और अनुमति में AndroidManifest.xml जोड़ें:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
...
<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
XML फ़ाइल प्रदाता res / xml / provider_paths.xml बनाएँ
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
नीचे दिए गए उदाहरण कोड का उपयोग करें:
public class InstallManagerApk extends AppCompatActivity {
static final String NAME_APK_FILE = "some.apk";
public static final int REQUEST_INSTALL = 0;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// required permission:
// android.Manifest.permission.WRITE_EXTERNAL_STORAGE
// android.Manifest.permission.READ_EXTERNAL_STORAGE
installApk();
}
...
/**
* Install APK File
*/
private void installApk() {
try {
File filePath = Environment.getExternalStorageDirectory();// path to file apk
File file = new File(filePath, LoadManagerApkFile.NAME_APK_FILE);
Uri uri = getApkUri( file.getPath() ); // get Uri for each SDK Android
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData( uri );
intent.setFlags( Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NEW_TASK );
intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
intent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, getApplicationInfo().packageName);
if ( getPackageManager().queryIntentActivities(intent, 0 ) != null ) {// checked on start Activity
startActivityForResult(intent, REQUEST_INSTALL);
} else {
throw new Exception("don`t start Activity.");
}
} catch ( Exception e ) {
Log.i(TAG + ":InstallApk", "Failed installl APK file", e);
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG)
.show();
}
}
/**
* Returns a Uri pointing to the APK to install.
*/
private Uri getApkUri(String path) {
// Before N, a MODE_WORLD_READABLE file could be passed via the ACTION_INSTALL_PACKAGE
// Intent. Since N, MODE_WORLD_READABLE files are forbidden, and a FileProvider is
// recommended.
boolean useFileProvider = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
String tempFilename = "tmp.apk";
byte[] buffer = new byte[16384];
int fileMode = useFileProvider ? Context.MODE_PRIVATE : Context.MODE_WORLD_READABLE;
try (InputStream is = new FileInputStream(new File(path));
FileOutputStream fout = openFileOutput(tempFilename, fileMode)) {
int n;
while ((n = is.read(buffer)) >= 0) {
fout.write(buffer, 0, n);
}
} catch (IOException e) {
Log.i(TAG + ":getApkUri", "Failed to write temporary APK file", e);
}
if (useFileProvider) {
File toInstall = new File(this.getFilesDir(), tempFilename);
return FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID, toInstall);
} else {
return Uri.fromFile(getFileStreamPath(tempFilename));
}
}
/**
* Listener event on installation APK file
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_INSTALL) {
if (resultCode == Activity.RESULT_OK) {
Toast.makeText(this,"Install succeeded!", Toast.LENGTH_SHORT).show();
} else if (resultCode == Activity.RESULT_CANCELED) {
Toast.makeText(this,"Install canceled!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,"Install Failed!", Toast.LENGTH_SHORT).show();
}
}
}
...
}
इसे इस्तेमाल करे
String filePath = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
String title = filePath.substring( filePath.lastIndexOf('/')+1, filePath.length() );
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(filePath)), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error!
MainActivity.this.startActivity(intent);
सबसे पहले AndroidManifest.xml में निम्न पंक्ति जोड़ें:
<uses-permission android:name="android.permission.INSTALL_PACKAGES"
tools:ignore="ProtectedPermissions" />
फिर APK स्थापित करने के लिए निम्न कोड का उपयोग करें:
File sdCard = Environment.getExternalStorageDirectory();
String fileStr = sdCard.getAbsolutePath() + "/MyApp";// + "app-release.apk";
File file = new File(fileStr, "TaghvimShamsi.apk");
Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
startActivity(promptInstall);
अपडेटनोड एंड्रॉइड के लिए एपीपी को दूसरे ऐप के अंदर से इंस्टॉल करने के लिए एक एपीआई प्रदान करता है।
आप बस अपने अपडेट को ऑनलाइन परिभाषित कर सकते हैं और एपीआई को अपने ऐप में एकीकृत कर सकते हैं - बस।
वर्तमान में एपीआई बीटा स्थिति में है, लेकिन आप पहले से ही कुछ परीक्षण स्वयं कर सकते हैं।
इसके अलावा, अपडेटनोड संदेश भी प्रदर्शित करता है, हालांकि सिस्टम - बहुत उपयोगी है यदि आप अपने उपयोगकर्ताओं को कुछ महत्वपूर्ण बताना चाहते हैं।
मैं क्लाइंट देव टीम का हिस्सा हूं और अपने एंड्रॉइड ऐप के लिए कम से कम मैसेज की कार्यक्षमता का उपयोग कर रहा हूं।
इसे आज़माएं - मैनिफेस्ट पर लिखें:
uses-permission android:name="android.permission.INSTALL_PACKAGES"
tools:ignore="ProtectedPermissions"
कोड लिखें:
File sdCard = Environment.getExternalStorageDirectory();
String fileStr = sdCard.getAbsolutePath() + "/Download";// + "app-release.apk";
File file = new File(fileStr, "app-release.apk");
Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
startActivity(promptInstall);