আমি কাস্টম অ্যান্ড্রয়েড অ্যাপ্লিকেশন থেকে ডায়নামিকভাবে ডাউনলোড করা অ্যাপকে প্রোগ্রাম্যালি ইনস্টল করা সম্ভব কিনা তা জানতে আগ্রহী।
আমি কাস্টম অ্যান্ড্রয়েড অ্যাপ্লিকেশন থেকে ডায়নামিকভাবে ডাউনলোড করা অ্যাপকে প্রোগ্রাম্যালি ইনস্টল করা সম্ভব কিনা তা জানতে আগ্রহী।
উত্তর:
আপনি সহজেই প্লে স্টোর লিঙ্ক বা একটি ইনস্টল প্রম্পট চালু করতে পারেন:
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+ এবং অন্যান্য ডিভাইসে এটি ভুল on 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()
উভয়ের জন্য মান দিতে চাইলে অবশ্যই ব্যবহার করা উচিত। এখানে: বিকাশকারী.অ্যান্ড্রয়েড.
এই প্রশ্নের প্রদত্ত সমাধানগুলি সমস্ত targetSdkVersion
23 এবং এর নীচে প্রযোজ্য । অ্যান্ড্রয়েড এন, অর্থাত্ এপিআই স্তর 24 এবং তারপরের জন্য, তবে তারা নিম্নলিখিত ব্যাতিক্রম দিয়ে কাজ করে না এবং ক্রাশ করে না:
android.os.FileUriExposedException: file:///storage/emulated/0/... exposed beyond app through Intent.getData()
এটি অ্যানড্রয়েড 24 থেকে শুরু Uri
করে, ডাউনলোড করা ফাইলটির ঠিকানা দেওয়ার জন্য পরিবর্তন হয়েছে to উদাহরণস্বরূপ, 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
এই পদক্ষেপগুলি অনুসরণ করতে হবে: অ্যান্ড্রয়েড ম্যানিফেস্ট.এক্সএমএলে নিম্নলিখিতটি যুক্ত করুন:
<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>
২. প্রধানত: এসআরসি- paths.xml
র xml
ফোল্ডারে নিম্নলিখিত ফাইলটি যুক্ত করুনres
<?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
যে উপরোক্ত দৃষ্টান্তমূলক বিষয়বস্তু URI উদাহরণে দেখানো আছে এবং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();
বাহ্যিক ফাইল সিস্টেমে আপনার নিজের অ্যাপের ব্যক্তিগত ডিরেক্টরিতে লেখার সময় কোনও অনুমতিও প্রয়োজন হয় না।
আমি এখানে একটি অটোআপেট লাইব্রেরি লিখেছি যেখানে আমি উপরেরটি ব্যবহার করেছি।
.authorityStr
after context.getPackageName()
ঠিক আছে, আমি আরও গভীর খনন করেছি এবং অ্যান্ড্রয়েড উত্স থেকে প্যাকেজইনস্টলার অ্যাপ্লিকেশনগুলির উত্স খুঁজে পেয়েছি।
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);
আমি কেবল এই সত্যটি শেয়ার করতে চাই যে আমার অ্যাপ্লিকেশন ফাইলটি আমার অ্যাপ্লিকেশন "ডেটা" ডিরেক্টরিতে সংরক্ষিত হয়েছিল এবং এপিকে ফাইলটি সেইভাবে ইনস্টল করার অনুমতি দেওয়ার জন্য বিশ্ব পঠনযোগ্য হওয়ার জন্য আমার অনুমতি পরিবর্তন করতে হবে, অন্যথায় সিস্টেমটি "পার্স ত্রুটি: প্যাকেজ পার্স করার ক্ষেত্রে একটি সমস্যা আছে" ছুড়েছিল; সুতরাং @ হোরেসম্যান থেকে সমাধান ব্যবহার করে যা তা তৈরি করে:
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>
তৃতীয়: নীচের মত রেজ / এক্সএমএল ফোল্ডারে পথ.এক্সএমএল সংজ্ঞায়িত করুন! আমি এই পথটি অভ্যন্তরীণ স্টোরেজের জন্য ব্যবহার করছি যদি আপনি এটিকে অন্য কোনও কিছুতে পরিবর্তন করতে চান তবে কয়েকটি উপায় আছে! আপনি এই লিঙ্কে যেতে পারেন: ফাইলপ্রভাইডার
<?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 টিরও বেশি বড় অ্যাপ্লিকেশনগুলিকে লক্ষ্যযুক্ত অ্যাপ্লিকেশনগুলিকে উদ্দেশ্য হিসাবে ব্যবহার করতে এই অনুমতিটি অবশ্যই রাখা উচিত CTION
সরবরাহকারী কর্তৃপক্ষগুলি সমান!
হ্যাঁ এটা সম্ভব. তবে তার জন্য আপনার যাচাই করা হয়নি এমন উত্স ইনস্টল করার জন্য ফোনটি দরকার। উদাহরণস্বরূপ, স্লাইডম এটি করে। আমি মনে করি যে অ্যাপ্লিকেশনটি উপস্থিত রয়েছে কিনা তা পরীক্ষা করে অ্যানড্রয়েড মার্কেটের জন্য একটি উদ্দেশ্য প্রেরণ করা আপনি সেরা কাজটি করতে পারেন। অ্যান্ড্রয়েড মার্কেটের জন্য আপনার কিছু ইউআরএল স্কিম ব্যবহার করা উচিত।
market://details?id=package.name
কীভাবে কার্যকলাপ শুরু করবেন তা আমি ঠিক জানি না তবে আপনি যদি এই জাতীয় url দিয়ে কোনও কার্যকলাপ শুরু করেন। এটি অ্যান্ড্রয়েড বাজার খুলতে হবে এবং অ্যাপ্লিকেশনগুলি ইনস্টল করার পছন্দ আপনাকে দেওয়া উচিত।
এটি লক্ষণীয় যে আপনি যদি 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
AndroidManLive.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 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);
প্রথমে AndroidManLive.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);
আপডেটনোড অ্যান্ড্রয়েডের জন্য অন্য অ্যাপ্লিকেশন থেকে APK প্যাকেজ ইনস্টল করতে একটি এপিআই সরবরাহ করে।
আপনি কেবলমাত্র আপনার আপডেটটিকে অনলাইনে সংজ্ঞায়িত করতে এবং আপনার অ্যাপ্লিকেশনটিতে API একীভূত করতে পারেন - এটি।
বর্তমানে এপিআই বিটা অবস্থায় রয়েছে তবে আপনি ইতিমধ্যে কিছু পরীক্ষা নিজেই করতে পারেন।
এর পাশাপাশি, আপডেটনোড সিস্টেম হিসাবেও বার্তা প্রদর্শন করার প্রস্তাব দেয় - আপনি যদি আপনার ব্যবহারকারীদের কাছে গুরুত্বপূর্ণ কিছু বলতে চান তবে বেশ কার্যকর pretty
আমি ক্লায়েন্ট দেব দলের অংশ এবং আমার নিজের অ্যান্ড্রয়েড অ্যাপের জন্য কমপক্ষে বার্তাটির কার্যকারিতাটি ব্যবহার করছি।
এটি ব্যবহার করে দেখুন - ম্যানিফেস্টে লিখুন:
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);