بسم الله الرحمن الرحيم
نستمر معكم بالدروس المتعلقة بالملفات الصوتية في مجال برمجة تطبيقات الأندرويد, ولكن اليوم سوف نقدم لكم مشروع صغير في كيفية تعيين نغمات الرنين.
# معاينة فيديو قصير للمشروع :
المشروع عبارة عن اكتفيتي واحدة, لذلك سوف اعرضها لكم هنا, ومن ثم تستطيع تحميل المشروع بالكامل.
وسوف يتم شرح بعض الأسطر المهمة المستخدمة في الكود وكيفية استخدامه.
MainActivity.java
package com.andrody.ringtone_android; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.AssetFileDescriptor; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.provider.Settings; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Toast; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /** * Created by Abboudi_Aliwi on 27.06.2017. * Website : https://andrody.com/ * our channel on YouTube : https://www.youtube.com/c/Andrody2015 * our page on Facebook : https://www.facebook.com/andrody2015/ * our group on Facebook : https://www.facebook.com/groups/Programming.Android.apps/ * our group on Whatsapp : https://chat.whatsapp.com/56JaImwTTMnCbQL6raHh7A * our group on Telegram : https://t.me/joinchat/AAAAAAm387zgezDhwkbuOA * Preview on YouTube : https://www.youtube.com/watch?v=w-DnZNwwBRY */ public class MainActivity extends AppCompatActivity { private MediaPlayer media_voice; private static final int REQUEST_CODE = 1; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); media_voice = new MediaPlayer(); if (Build.VERSION.SDK_INT >= 23) { requestPermission(); } } public void onClick(View v) { switch (v.getId()) { case R.id.but_t1: Play_Tone(R.raw.best_ringtone); break; case R.id.but_t2: Play_Tone(R.raw.shape_iphone); break; case R.id.but_t3: Play_Tone(R.raw.turkish_music); break; } } public void Play_Tone(int ID) { media_voice.stop(); media_voice.release(); media_voice = MediaPlayer.create(getApplicationContext(), ID); media_voice.start(); } public void onClick2(View v) { switch (v.getId()) { case R.id.set_t1: set_tone(getString(R.string.tone1),"best_ringtone"); break; case R.id.set_t2: set_tone(getString(R.string.tone2),"shape_iphone"); break; case R.id.set_t3: set_tone(getString(R.string.tone3),"turkish_music"); break; } } private void requestPermission() { if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) { Intent intent = new Intent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent); } else { ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE); } } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case REQUEST_CODE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (Build.VERSION.SDK_INT >= 23) { if (!Settings.System.canWrite(this)) { Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS) .setData(Uri.parse("package:" + getPackageName())) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } } } break; } } private void set_tone(String N1, String N2) { AssetFileDescriptor openAssetFileDescriptor; ((AudioManager) getSystemService(AUDIO_SERVICE)).setRingerMode(2); File file = new File(Environment.getExternalStorageDirectory() + "/AndRody", N2); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } Uri parse = Uri.parse("android.resource://"+ getPackageName()+"/raw/"+N2); ContentResolver contentResolver = getContentResolver(); try { openAssetFileDescriptor = contentResolver.openAssetFileDescriptor(parse, "r"); } catch (FileNotFoundException e2) { openAssetFileDescriptor = null; } try { byte[] bArr = new byte[1024]; FileInputStream createInputStream = openAssetFileDescriptor.createInputStream(); FileOutputStream fileOutputStream = new FileOutputStream(file); for (int read = createInputStream.read(bArr); read != -1; read = createInputStream.read(bArr)) { fileOutputStream.write(bArr, 0, read); } fileOutputStream.close(); } catch (IOException e3) { e3.printStackTrace(); } ContentValues contentValues = new ContentValues(); contentValues.put("_data", file.getAbsolutePath()); contentValues.put("title", N1); contentValues.put("mime_type", "audio/mp3"); contentValues.put("_size", Long.valueOf(file.length())); contentValues.put("is_ringtone", Boolean.valueOf(true)); try { Toast.makeText(this, new StringBuilder().append("تم تعيين النغمة بنجاح"), Toast.LENGTH_LONG).show(); RingtoneManager.setActualDefaultRingtoneUri(getBaseContext(), 1, contentResolver.insert(MediaStore.Audio.Media.getContentUriForPath(file.getAbsolutePath()), contentValues)); } catch (Throwable th) { Toast.makeText(this, new StringBuilder().append("يوجد خلل ما"), Toast.LENGTH_LONG).show(); } } @Override public void onDestroy() { super.onDestroy(); media_voice.release(); } }
الكود, يحتوي على استخدام/ تشغيل الملفات الصوتية, صلاحيات للوصول إلى خاصية التخزين في الاجهزة التي تعمل على أجهزة الاندرويد 23 واعلى, لتخزين الملف الصوتي بداخل ملفات الجهاز ومن ثم استخدامه نغمة رنين افتراضية للجهاز.
if (Build.VERSION.SDK_INT >= 23) { requestPermission(); }
طلب الصلاحيات بداية تشغيل التطبيق, للوصول إلى التخزين فقط للاجهزة التي تعمل على اصدار 23 واعلى, أما الإصدارات الأقل من ذلك, فهي لا تحتاج إلى صلاحيات من المستخدم. وكذلك الوصول إلى تعديل الاعدادات الافتراضية للجهاز, لتعيين النغمات.
public void onClick(View v)
دالة يتم تنفيذها بعد الضغط على الزر التشغيل, ويتم التعرف على ازرار التشغيل وحسب كل زر يتم ارسال الملف الصوتي الخاص به
public void Play_Tone(int ID)
الدالة التي يتم تنفيذها بعد استقبال الملف الصوتي ومن ثم تشغيله من خلال الضغط على زر التشغيل
public void onClick2(View v)
الدالة التي يتم تشغيلها وعملها بعد الضغط على نص تعيين النغمة ” SET ” وحسب كل زر يتم تفعيل الدالة set_tone ,وارسال معها نصين, مثلاً :
set_tone(getString(R.string.tone1),"best_ringtone");
النص الأول : R.string.tone1 وهو الأسم الذي تريده للنغمة, وقد تم جلبه من السترنج وهو نفسه الاسم الذي يظهر في رئيسية التطبيق, وهو نفسه الذي يظهر في الاعدادات في جهاز المستخدم.
النص الثاني : best_ringtone ,وهو اسم الملف الصوتي الموجود بداخل المجلد raw.
requestPermission()
onRequestPermissionsResult
دالة التأكد من صلاحيات التخزين.
onDestroy()
في حال تم ايقاف التطبيق, يتم ايقاف الملف الصوتي.
ما ذكرته ليس إلا سطور تعليقات, ويفضل قرائتها .. ولم أقم بشرحها بالتفصيل العلمي, ولم أقم بذلك من قبل, لأن الفئة الموجه لها الموقع هي المبتدئة في مجال برمجة تطبيقات الأتدرويد.
الكود جداً واضح وسهل الاستخدام, ومقسم إلى دوال واضحة.
وهنا أشرح كيفية استخدام الكود للمبتدئين تماماً في كيفية إضافة النغمات للتطبيق :
- قم بوضع الملفات الصوتية في المجلد التالي : app\src\main\res\raw
- في ملف اللياوت الواجهة activity_main.xml يوجد سطور ملاحظات وسوف تجد
<!– LinearLayout TONE 1 –>
انسخ الكود أسفلها حتى تصل إلى <!– LinearLayout TONE 2 –>
فهذه اللينرلياوت لكل عنصر وملف صوتي. - وقم لصقها بالأسفل بالقدر الذي تريده, حسب عدد الملفات الصوتية التي تم اضافتها.
- فقط مع نغيير : نصوص السترنج, الـ ID الخاص بكل زر تشغيل ونص تعيين.
- ثم في ملف الجافا MainActivity تجد إن هناك أوامر مرقمة 3 مرات على عدد الملفات الصوتية, قم بنسخ منها للملفات الصوتية الباقية مع تغيير المطلوب.
- ولا تنسى إضافة اسماء الملفات الصوتية في الجافا وإسمائها في ملفات السترنج.
# تحميل الكود :
تستطيع تصفح الكود وتحميل من موقع github, من خلال الضغط على : سبحان الله.
انتظرونا في المزيد من الأعمال الحصرية والجديدة لكم .. وشكراً لكل من دعمنا في الاستمرار بمشروع اندرودي عربي.