ambient sound values - Android Software Development

hello
I would like to get the values from a sample of an ambient sounds phone absorbs from it's surroundings. how can I able to do so?
i.e how do I sample, and then how do I get values, and in which form?
thanks,
Doron

i know no way of getting the sound levels from the mic without recording a file and doing some sort of audio analysis on it.
see http://developer.android.com/reference/android/media/MediaRecorder.html
and (not my code...)
Code:
public class AudioRecorder {
final MediaRecorder recorder = new MediaRecorder();
final String path;
/**
* Creates a new audio recording at the given path (relative to root of SD card).
*/
public AudioRecorder(String path) {
this.path = sanitizePath(path);
}
private String sanitizePath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.contains(".")) {
path += ".3gp";
}
return Environment.getExternalStorageDirectory().getAbsolutePath() + path;
}
/**
* Starts a new recording.
*/
public void start() throws IOException {
String state = android.os.Environment.getExternalStorageState();
if(!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
throw new IOException("SD Card is not mounted. It is " + state + ".");
}
// make sure the directory we plan to store the recording in exists
File directory = new File(path).getParentFile();
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Path to file could not be created.");
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(path);
recorder.prepare();
recorder.start();
}
/**
* Stops a recording that has been previously started.
*/
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
}

thanks a lot.

Related

Direct X and PNG Transparency on WM6.1 with .Net CF3.5

Hi all,
I'm trying to have transparent PNGs on my screen.
What is the best way to doing this ? I'm in C#, I tried DirectX, but it doesn't work.
What am I doing wrong ?
My code :
Code:
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.WindowsMobile.DirectX;
using Microsoft.WindowsMobile.DirectX.Direct3D;
using System.Runtime.InteropServices;
namespace Microsoft.Samples.MD3DM
{
// The main class for this sample
public class SimpleSMS : Form
{
// Our global variables for this project
Device device = null;
Texture texture = null;
Sprite sprite = null;
Rectangle rect;
public SimpleSMS()
{
// Set the caption
this.Text = "SimpleSMS";
this.MinimizeBox = false;
}
// Prepare the rendering device
public bool InitializeGraphics()
{
try
{
// Now let's setup our D3D parameters
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
device = new Device(0, DeviceType.Default, this, CreateFlags.None, presentParams);
this.OnCreateDevice(device, null);
}
catch (DirectXException)
{
return false;
}
return true;
}
void OnCreateDevice(object sender, EventArgs e)
{
texture = TextureLoader.FromFile(device, @"badge.png");
sprite = new Sprite(device);
rect = new Rectangle(0, 0, 48, 48);
}
// All rendering for each frame occurs here
private void Render()
{
if (device != null)
{
device.Clear(ClearFlags.Target, System.Drawing.Color.Black, 1.0f, 0);
//Begin the scene
device.BeginScene();
device.RenderState.SourceBlend = Blend.SourceAlpha;
device.RenderState.DestinationBlend = Blend.InvSourceAlpha;
device.RenderState.AlphaBlendEnable = true;
sprite.Begin(SpriteFlags.AlphaBlend);
sprite.Draw(texture, rect, new Vector3(0.0f, 0.0f, 0.0f), new Vector3(100.0f, 100.0f, 0.0f), Color.White.ToArgb());
sprite.End();
//End the scene
device.EndScene();
device.Present();
}
}
// Called to repaint the window
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
// Render on painting
this.Render();
// Render again
this.Invalidate();
}
// Called to repaint the window background
protected override void OnPaintBackground(
System.Windows.Forms.PaintEventArgs e)
{
// Do nothing to ensure that the rendering area is not overdrawn
}
// Close the window when Esc is pressed
protected override void OnKeyPress(
System.Windows.Forms.KeyPressEventArgs e)
{
// Esc was pressed
if ((int)(byte)e.KeyChar == (int)System.Windows.Forms.Keys.Escape)
this.Close();
}
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
SimpleSMS frm = new SimpleSMS();
// Initialize Direct3D
if (!frm.InitializeGraphics())
{
MessageBox.Show("Could not initialize Direct3D. " +
"This tutorial will exit.");
return;
}
Application.Run(frm);
}
}
}
Thanks for answers,
Scuse my bad english :-/
Not sure this helps, but RLTODAY works very well with transparent pngs in any WM version, and recently he released the source code:
http://rotlaus-software.de/forum/index.php?topic=1847.0
You can use ImagingFactory in OpenNETCF or other wrapper over the internet. PNGs with alpha work work for me.
AlphaControls
There is a project on Codeplex that can help you with transparency called AlphaControls. Also have a look on codeproject at the iPhone app clone
moneytoo said:
You can use ImagingFactory in OpenNETCF or other wrapper over the internet. PNGs with alpha work work for me.
Click to expand...
Click to collapse
Thank you all for answers ...
I tried OpenNetCF, without any result.
Do you have a piece of code in example ?
Try this:
http://www.codeplex.com/alphamobilecontrols
Or this:
http://johan.andersson.net/blog/2007/10/solution-for-transparent-images-on.html

[source code] Viewpager containing preferencescreens

Hi,
since the compability package does not ship PreferenceListFragment, I built my own one, which I am using in my gtalk widget app.
I was asked for the source, so here it is. It's quite a hacky workaround..
Edit: Someone asked about the license: Use it however you like
Code:
public class PreferenceListFragment extends ListFragment{
private PreferenceManager mPreferenceManager;
/**
* The starting request code given out to preference framework.
*/
private static final int FIRST_REQUEST_CODE = 100;
private static final int MSG_BIND_PREFERENCES = 0;
private Handler mHandler = new Handler() {
[user=439709]@override[/user]
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_BIND_PREFERENCES:
bindPreferences();
break;
}
}
};
private ListView lv;
private int xmlId;
public PreferenceListFragment(int xmlId){
this.xmlId = xmlId;
}
//must be provided
public PreferenceListFragment(){
}
[user=439709]@override[/user]
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle b){
postBindPreferences();
return lv;
}
[user=439709]@override[/user]
public void onDestroyView(){
super.onDestroyView();
ViewParent p = lv.getParent();
if(p != null)
((ViewGroup)p).removeView(lv);
}
[user=439709]@override[/user]
public void onCreate(Bundle b) {
super.onCreate(b);
if(b != null)
xmlId = b.getInt("xml");
mPreferenceManager = onCreatePreferenceManager();
lv = (ListView) LayoutInflater.from(getActivity()).inflate(R.layout.preference_list_content, null);
lv.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
addPreferencesFromResource(xmlId);
postBindPreferences();
((OnPreferenceAttachedListener)getActivity()).onPreferenceAttached(getPreferenceScreen(), xmlId);
}
[user=439709]@override[/user]
public void onStop(){
super.onStop();
try{
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityStop");
m.setAccessible(true);
m.invoke(mPreferenceManager);
}catch(Exception e){
e.printStackTrace();
}
}
[user=439709]@override[/user]
public void onDestroy() {
super.onDestroy();
lv = null;
try{
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityDestroy");
m.setAccessible(true);
m.invoke(mPreferenceManager);
}catch(Exception e){
e.printStackTrace();
}
}
[user=439709]@override[/user]
public void onSaveInstanceState(Bundle outState) {
outState.putInt("xml", xmlId);
super.onSaveInstanceState(outState);
}
[user=439709]@override[/user]
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try{
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class);
m.setAccessible(true);
m.invoke(mPreferenceManager, requestCode, resultCode, data);
}catch(Exception e){
e.printStackTrace();
}
}
/**
* Posts a message to bind the preferences to the list view.
* <p>
* Binding late is preferred as any custom preference types created in
* {@link #onCreate(Bundle)} are able to have their views recycled.
*/
private void postBindPreferences() {
if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
}
private void bindPreferences() {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
if (preferenceScreen != null) {
preferenceScreen.bind(lv);
}
}
/**
* Creates the {@link PreferenceManager}.
*
* [user=2056652]@return[/user] The {@link PreferenceManager} used by this activity.
*/
private PreferenceManager onCreatePreferenceManager() {
try{
Constructor<PreferenceManager> c = PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class);
c.setAccessible(true);
PreferenceManager preferenceManager = c.newInstance(this.getActivity(), FIRST_REQUEST_CODE);
return preferenceManager;
}catch(Exception e){
e.printStackTrace();
return null;
}
}
/**
* Returns the {@link PreferenceManager} used by this activity.
* [user=2056652]@return[/user] The {@link PreferenceManager}.
*/
public PreferenceManager getPreferenceManager() {
return mPreferenceManager;
}
/**
* Sets the root of the preference hierarchy that this activity is showing.
*
* [user=955119]@param[/user] preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
*/
public void setPreferenceScreen(PreferenceScreen preferenceScreen){
try{
Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
m.setAccessible(true);
boolean result = (Boolean) m.invoke(mPreferenceManager, preferenceScreen);
if (result && preferenceScreen != null) {
postBindPreferences();
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* Gets the root of the preference hierarchy that this activity is showing.
*
* [user=2056652]@return[/user] The {@link PreferenceScreen} that is the root of the preference
* hierarchy.
*/
public PreferenceScreen getPreferenceScreen(){
try{
Method m = PreferenceManager.class.getDeclaredMethod("getPreferenceScreen");
m.setAccessible(true);
return (PreferenceScreen) m.invoke(mPreferenceManager);
}catch(Exception e){
e.printStackTrace();
return null;
}
}
/**
* Adds preferences from activities that match the given {@link Intent}.
*
* [user=955119]@param[/user] intent The {@link Intent} to query activities.
*/
public void addPreferencesFromIntent(Intent intent) {
throw new RuntimeException("too lazy to include this bs");
}
/**
* Inflates the given XML resource and adds the preference hierarchy to the current
* preference hierarchy.
*
* [user=955119]@param[/user] preferencesResId The XML resource ID to inflate.
*/
public void addPreferencesFromResource(int preferencesResId) {
try{
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
m.setAccessible(true);
PreferenceScreen prefScreen = (PreferenceScreen) m.invoke(mPreferenceManager, getActivity(), preferencesResId, getPreferenceScreen());
setPreferenceScreen(prefScreen);
}catch(Exception e){
e.printStackTrace();
}
}
/**
* Finds a {@link Preference} based on its key.
*
* [user=955119]@param[/user] key The key of the preference to retrieve.
* [user=2056652]@return[/user] The {@link Preference} with the key, or null.
* [user=690402]@see[/user] PreferenceGroup#findPreference(CharSequence)
*/
public Preference findPreference(CharSequence key) {
if (mPreferenceManager == null) {
return null;
}
return mPreferenceManager.findPreference(key);
}
public interface OnPreferenceAttachedListener{
public void onPreferenceAttached(PreferenceScreen root, int xmlId);
}
}
How to use:
Code:
public class Settings extends FragmentActivity implements OnPreferenceAttachedListener, OnPreferenceChangeListener, OnPreferenceClickListener{
private Preference filterPref;
private ViewPager viewPager;
public void onCreate(Bundle b){
super.onCreate(b);
setContentView(R.layout.settings);
viewPager = (ViewPager) findViewById(R.id.pager);
PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(), this);
viewPager.setAdapter(adapter);
TitlePageIndicator titleIndicator = (TitlePageIndicator) findViewById(R.id.titles);
titleIndicator.setViewPager(viewPager);
titleIndicator.setFooterIndicatorStyle(IndicatorStyle.Underline);
viewPager.setCurrentItem(1);
}
//setup your onPreferenceClickListener/onPreferenceChangeListener here
[user=439709]@override[/user]
public void onPreferenceAttached(PreferenceScreen root, int xmlId){
if(root == null)
return; //for whatever reason in very rare cases this is null
if(xmlId == R.xml.widget_settings){ //example id
root.findPreference("somePreference").setOnPreferenceClickListener(this);
}
}
//handle your preferenceChanged events here (if needed)
[user=439709]@override[/user]
public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
//handle your preferenceClick events here (if needed)
[user=439709]@override[/user]
public boolean onPreferenceClick(Preference pref){
return true;
}
}
and the adapter I am using:
Code:
public class PagerAdapter extends FragmentPagerAdapter implements TitleProvider{
PreferenceListFragment[] fragments;
String[] titles;
public PagerAdapter(FragmentManager fm, Context context) {
super(fm);
fragments = new PreferenceListFragment[4];
fragments[0] = new PreferenceListFragment(R.xml.settings);
fragments[1] = new PreferenceListFragment(R.xml.widget_settings);
fragments[2] = new PreferenceListFragment(R.xml.s_widget_settings);
fragments[3] = new PreferenceListFragment(R.xml.color_settings);
titles = new String[4];
titles[0] = context.getString(R.string.main_settings);
titles[1] = context.getString(R.string.widget_settings);
titles[2] = context.getString(R.string.s_widget_settings);
titles[3] = context.getString(R.string.color_settings_main);
}
[user=439709]@override[/user]
public Fragment getItem(int position){
return fragments[position];
}
[user=439709]@override[/user]
public int getCount() {
return fragments.length;
}
[user=439709]@override[/user]
public String getTitle(int position) {
return titles[position];
}
}
Lastly you will need this xml file: preference_list_content.xml (belongs into /res/layout/) (pulled from aosp)
Code:
<?xml version="1.0" encoding="utf-8"?>
<!--
/* //device/apps/common/assets/res/layout/list_content.xml
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:drawSelectorOnTop="false"
android:scrollbarAlwaysDrawVerticalTrack="true"
/>
Thanks for sharing.
=]
Thank you for sharing!
THANK YOU, much appropriated
Working fine on my devices (Nexus S and GNex), but received logs with crashes here:
Code:
((OnPreferenceAttachedListener)getActivity()).onPreferenceAttached(getPreferenceScreen(), xmlId);
NullPointerException here:
Code:
@Override
public void onPreferenceAttached(PreferenceScreen root, int xmlId) {
List<PreferenceScreen> rootPref=new ArrayList<PreferenceScreen>() ;
rootPref.add(root);
root.getSharedPreferences().registerOnSharedPreferenceChangeListener(
this);
hm, I received logs, that the listview is null when bindPreferences() is called. =/
thank you, i will use this on my application NSTools
Hello, i ma new at this and i am trying to understand the code, what exactly are "R.array.display_filter_array" and "R.layout.preference_list_content", these are the only things i have left to try this code, hope you can help me
Thank you
I added the missing layout file in the first post.
I also added a check for nullpointer in onPreferenceAttached().
R.array.display_filter_array correspondends to a string array I defined.
getResources().getStringArray(int stringId) will return an array of localized strings defined in res/values/strings.xml.
Thank you so much for this! I've been wracking my brain for a long time to come up with a way to use a PreferenceFragment on pre-Honeycomb devices, and this fits my needs exactly. So much love.
I'll let you know if I run across any issues.
Hi.
First I'd like to thank you for sharing this.
I have an issue with this : each preference row is only taking the width it's really nead, instead of using all width available like any Preference view. The result is kinda ugly (widgets of preferences not aligned in the right and click area way too little).
But if I start a new Activity and come back, they are well displayed. The only difference between the code I use and yours is I don't use a ViewPage, I directly use the ListFragment as Fragment.
Can someone help me please ?
Thanks in advance.
Hey guys, I just wanted to share a different initialization scheme. I couldn't get the activity to survive orientation change without fc. So i came up with this...
Extended PreferenceFragment
Code:
package org.teameos.settings.device;
import android.os.Bundle;
public class DiagPreferences extends PreferenceListFragment {
public static DiagPreferences newInstance(int xml) {
DiagPreferences f = new DiagPreferences(xml);
Bundle b = new Bundle();
b.putInt("xml", xml);
f.setArguments(b);
return f;
}
public DiagPreferences(int xmlId) {
// TODO Auto-generated constructor stub
super(xmlId);
}
public DiagPreferences() {
super();
}
The adapter
Code:
public ViewPagerAdapter(Context context, FragmentManager fm) {
super(fm);
mContext = context;
mFragments = new ArrayList<Pair<Fragment, String>>();
mFragments.add(Pair.create(
(Fragment) UpdatesPreferences.newInstance(R.xml.updates_and_menus),
mContext.getString(R.string.eos_ota_menus)));
mFragments.add(Pair.create((Fragment) DiagPreferences.newInstance(R.xml.diagnostics),
mContext.getString(R.string.eos_diag)));
mFragments.add(Pair.create((Fragment) PrlPreferences.newInstance(R.xml.prl_management),
mContext.getString(R.string.prl_management)));
}
using the above code (you cant use constructors) and using newInstance its not working
you need modify this in Oncreate
Code:
super.onCreate(b);
if(b != null){
xmlId = b.getInt("xml");
}else
{
xmlId = getArguments().getInt("xml");
}
This code gave me a warning about memory leak we shouls use WeakReference or use as static
Code:
private Handler mHandler = new Handler() {
[user=439709]@override[/user]
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_BIND_PREFERENCES:
bindPreferences();
break;
}
}
};
like this:
Code:
private [B][COLOR="Red"]static[/COLOR] [/B]Handler mHandler = new Handler() {
[user=439709]@override[/user]
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_BIND_PREFERENCES:
bindPreferences();
break;
}
}
};
and in all "dependencies" of that function like bindPreferences and so on.
Ps AMAZING Work BTW thanks a lot
Great code, but I can't find TitleProvider anywhere... I believe it used to be part of PagerViewer? How to remove this?

How can I run a command from user-selected choice (array)

A user can select an item from my view to get a dialog showing different strings. Below that is a button. I would like the button, when pressed, to run a shell command. I have no idea how I would go about doing this.
Basically, how can I make the button have a command set to it, which when a user selects something in the dialog popup, runs the command + the string in the chosen view?
The class:
Code:
public static class DataSyncPreferenceFragment extends PreferenceFragment {
[user=439709]@override[/user]
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_data_sync);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("sync_frequency"));
}
}
The button
Code:
public void button1(View v) {
switch (v.getId()) {
case R.id.button1:
try {
Runtime.getRuntime().exec(new String[] { "su", "-c","HOW_DO_I_ADD_THINGS_HERE" });
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
My arrays look like this:
Code:
<string-array name="pref_sync_frequency_titles">
<item>Normal</item>
<item>Smaller</item>
<item>Smallest</item>
</string-array>
<string-array name="pref_sync_frequency_values">
<item>320</item>
<item>280</item>
<item>220</item>
</string-array>
Any help would be appreciated. I'm too new to know these things, sadly. :crying:
Here's a possible solution to what you're trying to achieve. I've had to implement something like this in my apps before, and I've made use of this helpful StackOverflow question.
Code:
new AlertDialog.Builder(this.getActivity())
//Add your titles array to the dialog (in single choice mode)
.setSingleChoiceItems(R.array.pref_sync_frequency_titles, 0, null)
.setPositiveButton(R.string.ok_button_label, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
int selectedPosition = ((AlertDialog)dialog).getListView().getCheckedItemPosition();
//Get the corresponding values Array
String[] strValues = getActivity().getResources().getStringArray(R.array.pref_sync_frequency_values);
//Get the corresponding value that was clicked
String yourValue = strValues[selectedPosition];
try {
Runtime.getRuntime().exec(new String[] { "su", "-c","HOW_DO_I_ADD_THINGS_HERE" + yourValue });
} catch (IOException e) {
e.printStackTrace();
}
}
})
.show();
Let me know how that works!

setActualDefaultRingtoneUri(,RingtoneManager.TYPE_ RING,) not work on s7 edge

Hi guys, could anyone help me with this?
I am trying to develop an application that could automatic change the ringtone for incoming calls, because all the existed applications which has this feature could not works well on my Galaxy S7 Edge,
but then I found out is't not that easy to change ringtone on Galaxy S7 Edge.
I am tried with these code:
File sdFile = new File("/mnt/storage/26D9-150C/test.mp3");
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, sdFile.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, sdFile.getName());
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.Media.IS_ALARM, false);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(sdFile.getAbsolutePath());
getContentResolver().delete(uri ,null ,null);//if not delete, maybe it will cause some error.
Uri newUri = this.getContentResolver().insert(uri, values);
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, newUri);
These code works fine on other devices, also on the Galaxy S7 Edge, you can see the new ringtone with code below, the ringtone changed into the target file, but when you received a phone call it's not the the ringtone that I set ! It's still the old ringtone before I run that code above. What's the problem ????? And I checked the ringtone from "Setting-Sound and vibrate-ringtone-incoming ringtone" it's never changed!!!
And I have granted the WRITE_SETTINGS permission already.
private Uri getSystemDefaultRingtoneUri() {
return RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE);//RingtoneManager.TYPE_ALL
}
private String getRealPath(Uri fileUrl) {
String fileName = null;
Uri filePathUri = fileUrl;
if (fileUrl != null) {
if (fileUrl.getScheme().toString().compareTo("content") == 0) {
Cursor cursor = mContext.getContentResolver().query(fileUrl, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
fileName = cursor.getString(column_index);
if (!fileName.startsWith("/mnt")) {
fileName = "/mnt" + fileName;
}
cursor.close();
}
} else if (fileUrl.getScheme().compareTo("file") == 0) {
fileName = filePathUri.toString().replace("file://", "");
if (!fileName.startsWith("/mnt")) {
fileName += "/mnt";
}
}
}
return fileName;
}
Then I searched everywhere, and find out that it seems samsung changed the system, the TYPE_RINGTONE will not effect on samsung anymore, is it true ? How could fix this problem ?
Why samsung change it like this ? It's really ****ty for developers!
Could anyone help me ? Thank you!
And here is all the code:
public class ActivityMain extends AppCompatActivity {
private static final boolean d = true;
private Context mContext;
@override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
initView();
checkMyPermission(false);
}
private boolean checkMyPermission(boolean isSecondTimeCheck) {
String dialogTitle = "need WRITE_SETTINGS permission";
if (isSecondTimeCheck) dialogTitle = "you deny the permission";
String btnTitle = "ok", if (isSecondTimeCheck) btnTitle = "try again";
if (Build.VERSION.SDK_INT >= 23) {
if (!Settings.System.canWrite(this)) {
new AlertDialog.Builder(mContext).setMessage(dialogTitle).setPositiveButton(btnTitle, new DialogInterface.OnClickListener() {
 @override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE_PERMISSION);
}
}).setNegativeButton("cancel", null).create().show();
return false;
}
return true;
} else {
int hasWriteContactsPermission = ContextCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_SETTINGS);
if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
new AlertDialog.Builder(mContext).setMessage(dialogTitle).setPositiveButton(btnTitle, new DialogInterface.OnClickListener() {
 @override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE_PERMISSION);
}
}).setNegativeButton("cancel", null).create().show();
return false;
} else {
return true;
}
}
}
private void initView() {
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
 @override
public void onClick(View view) {
//TODO I added the event here, it's more easier......this is the automatic method
// Log.d("tag", "original ringtone before set new ringtone" + getRealPath(getSystemDefaultRingtoneUri()));
// setMyRingtone("/mnt/storage/26D9-150C/0_MyFiles/8.Others/New_Eng_Rings_15.09.03/Blame it on me - akon - A.mp3");
// //setMyRingtone("/mnt/storage/26D9-150C/0_MyFiles/8.Others/New_Eng_Rings_15.09.03/Birthmark - akon - A.mp3");
//TODO here is the 2nd method, manual setting also not work....
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "Choose the new ringtone");
startActivityForResult(intent, REQUEST_CODE_CHOOSE_RINGTONE_BY_USER);
}
});
}
private static final int REQUEST_CODE_PERMISSION = 1;
private static final int REQUEST_CODE_CHOOSE_RINGTONE_BY_USER = 2;
private void setMyRingtone(String path) {
File sdFile = new File(path);
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, sdFile.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, sdFile.getName());
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.Media.IS_ALARM, false);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(sdFile.getAbsolutePath());
getContentResolver().delete(uri, null, null);
Uri newUri = this.getContentResolver().insert(uri, values);
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, newUri);
Log.d("tag", "new ringtone has been set:" + getRealPath(getSystemDefaultRingtoneUri()));//you can see that the new ringtone has been set success!
}
private Uri getSystemDefaultRingtoneUri() {
return RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE);//RingtoneManager.TYPE_ALL
}
private String getRealPath(Uri fileUrl) {
String fileName = null;
Uri filePathUri = fileUrl;
if (fileUrl != null) {
if (fileUrl.getScheme().toString().compareTo("content") == 0) {
Cursor cursor = mContext.getContentResolver().query(fileUrl, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
fileName = cursor.getString(column_index);
if (!fileName.startsWith("/mnt")) {
fileName = "/mnt" + fileName;
}
cursor.close();
}
} else if (fileUrl.getScheme().compareTo("file") == 0) {
fileName = filePathUri.toString().replace("file://", "");
if (!fileName.startsWith("/mnt")) {
fileName += "/mnt";
}
}
}
return fileName;
}
/* 当设置铃声之后的回调函数 */
 @override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_PERMISSION:
checkMyPermission(true);
break;
case REQUEST_CODE_CHOOSE_RINGTONE_BY_USER:
if (resultCode == RESULT_OK) {
try {
Uri pickedUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
if (pickedUri != null) {
Log.d("tag", "new ringtone will be set into:" + getRealPath(pickedUri));
RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_RINGTONE, pickedUri);
Log.d("tag", "new ringtone has been set into:" + getRealPath(getSystemDefaultRingtoneUri()));
}
} catch (Exception e) {
if (d) e.printStackTrace();
}
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
}
Please help, thank you.
is anyone could help ?
help....
You need the
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
Permission. Only grantable for System apps.
nicholaschum said:
You need the
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
Permission. Only grantable for System apps.
Click to expand...
Click to collapse
Thanks for your reply.
I have this permission in my manifest.xml already.
It seems samsung ringtong not use the standard database...
Cooper.G said:
Thanks for your reply.
I have this permission in my manifest.xml already.
It seems samsung ringtong not use the standard database...
Click to expand...
Click to collapse
As I said, your app must be a system app (or a privileged app). Or else, adding this manifest to a normal app will not function at all and is useless.
nicholaschum said:
As I said, your app must be a system app (or a privileged app). Or else, adding this manifest to a normal app will not function at all and is useless.
Click to expand...
Click to collapse
Actually I think it's not the metter about the permission, the permission has been authorized, and the ringtone really changed into my ringtone on my device,
use these code you can see the default ringtone has changed after set.
private Uri getSystemDefaultRingtoneUri() {
return RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE);//RingtoneManager.TYPE_ALL
}
Also use a different application to check the default ringtone, it's changed into the one that I choosen.
But in fact the the ring of incoming call from the speaker never changed.
So I think samsung use a different ringtone database or whatever.
Oh, and all kinds of random ringtong tools not work on S7edge.
I will try to figure it out when I rooted my s7edge.
And before this, I found some information about samsung ring of alarm, so I think the call maybe the same reason, http://bbs.anzhuo.cn/thread-938419-1-1.html
anyway, thanks for reply.
nicholaschum said:
As I said, your app must be a system app (or a privileged app). Or else, adding this manifest to a normal app will not function at all and is useless.
Click to expand...
Click to collapse
And here is the way for android 6.0.1 to ask the WRITE_SETTINGS permission
private boolean checkMyPermission(boolean isSecondTimeCheck) {
String dialogTitle = "need WRITE_SETTINGS permission";
if (isSecondTimeCheck) dialogTitle = "you deny the permission";
String btnTitle = "ok", if (isSecondTimeCheck) btnTitle = "try again";
if (Build.VERSION.SDK_INT >= 23) {
if (!Settings.System.canWrite(this)) {
new AlertDialog.Builder(mContext).setMessage(dialogTit le).setPositiveButton(btnTitle, new DialogInterface.OnClickListener() {
 @override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE_PERMISSION);
}
}).setNegativeButton("cancel", null).create().show();
return false;
}
return true;
} else {
int hasWriteContactsPermission = ContextCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_SETTINGS);
if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
new AlertDialog.Builder(mContext).setMessage(dialogTit le).setPositiveButton(btnTitle, new DialogInterface.OnClickListener() {
 @override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE_PERMISSION);
}
}).setNegativeButton("cancel", null).create().show();
return false;
} else {
return true;
}
}
}
Cooper.G said:
Actually I think it's not the metter about the permission, the permission has been authorized, and the ringtone really changed into my ringtone on my device,
use these code you can see the default ringtone has changed after set.
private Uri getSystemDefaultRingtoneUri() {
return RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE);//RingtoneManager.TYPE_ALL
}
Also use a different application to check the default ringtone, it's changed into the one that I choosen.
But in fact the the ring of incoming call from the speaker never changed.
So I think samsung use a different ringtone database or whatever.
Oh, and all kinds of random ringtong tools not work on S7edge.
I will try to figure it out when I rooted my s7edge.
And before this, I found some information about samsung ring of alarm, so I think the call maybe the same reason, http://bbs.anzhuo.cn/thread-938419-1-1.html
anyway, thanks for reply.
Click to expand...
Click to collapse
The permission has NOT been authorized. Please try to wrap your head around this. Your code is really messy.
https://github.com/android/platform_frameworks_base/blob/master/core/res/AndroidManifest.xml#L1597
Line 1600 states that you must have built the system through same firmware signature, "preinstalled" (priv-app), appop and pre-23 API
1595 states that it has a protection level of signature meaning that if the app isn't signed with the same signature as the ROM it won't be authorized to use that permission.
You can also try "pm grant YOUR_APP_NAME android.permission.WRITE_SETTINGS" in adb shell - and you will get an error saying it isn't a grantable permission.
Finally, if your app is a downloadable app from Play Store, this is the only caveat. Unless you request root to priv-app, THIS PERMISSION ISN'T GRANTED.
Java:
private boolean checkWriteSettingsPermissions() {
String permission = "android.permission.WRITE_SETTINGS";
int res = getContext().checkCallingOrSelfPermission(permission);
return (res == PackageManager.PERMISSION_GRANTED);
}
This is simple code that allows you to check whether your app is granted the permission.
nicholaschum said:
The permission has NOT been authorized. Please try to wrap your head around this. Your code is really messy.
https://github.com/android/platform_frameworks_base/blob/master/core/res/AndroidManifest.xml#L1597
Line 1600 states that you must have built the system through same firmware signature, "preinstalled" (priv-app), appop and pre-23 API
1595 states that it has a protection level of signature meaning that if the app isn't signed with the same signature as the ROM it won't be authorized to use that permission.
You can also try "pm grant YOUR_APP_NAME android.permission.WRITE_SETTINGS" in adb shell - and you will get an error saying it isn't a grantable permission.
Finally, if your app is a downloadable app from Play Store, this is the only caveat. Unless you request root to priv-app, THIS PERMISSION ISN'T GRANTED.
Java:
private boolean checkWriteSettingsPermissions() {
String permission = "android.permission.WRITE_SETTINGS";
int res = getContext().checkCallingOrSelfPermission(permission);
return (res == PackageManager.PERMISSION_GRANTED);
}
This is simple code that allows you to check whether your app is granted the permission.
Click to expand...
Click to collapse
Thank you for your patient.
1. I tried your code, and I was wrong about the permission, it says PERMISSION_DENIED. but I think this is not the problem for this question.
2. Did you tried my code ? The way that I asked for "WRITE_SETTINGS" is really work for ringtone, altho
Java:
private boolean checkWriteSettingsPermissions() {
String permission = "android.permission.WRITE_SETTINGS";
int res = getContext().checkCallingOrSelfPermission(permission);
return (res == PackageManager.PERMISSION_GRANTED);
}
said "PERMISSION_DENIED" , but it's really changed the ringtone ! If you not believe this, please try by yourself, and you can see from the setting - ring and vibrate - ringtone , you can see the result.
3. After several times try, I figure it out now... both way(manual and auto set by code "setMyRingtone()") of set the ringtone will work on the phone if have the permission of "Settings.System.canWrite(this)", but only work for the Ringtone of SIM 1, not work for SIM2. you can see the result form the setting page(only the ringtone for sim1 will change). if the ringtone still play the default ring of system, the problem probably is the metter of URI .
4. Before I post this thread, both way won't change the result of ringtone from the setting page of the phone, but as I said , you can see the result form another third part application.(this problem most probably is that I only use one SIM card at that time, did I put it into sim2? I don't know, already forget... but now if I put it into sim2 the ringtone form the setting page of the phone never change, but from the log of the code you can see the result is correct actually.)
5. Now the problem change into "How to create a standard URI and how to change the ringtone for SIM2". I will try to work on it.
6. Sorry for my pool English, and sorry for the "messy" code, I will improve it.
Anyway , thank you. you r the only one who helped me... Wish u luck.
Cooper.G said:
6. Sorry for my pool English, and sorry for the "messy" code, I will improve it.
Click to expand...
Click to collapse
I had the ringtone added on my MediaProvider but not set as the current one, I believe AOSP and TW deving is different.
When I mentioned "messy" I meant just copying and pasting the code into the forum, use
Code:
tags next time so it formats perfectly! :good::highfive:
nicholaschum said:
I had the ringtone added on my MediaProvider but not set as the current one, I believe AOSP and TW deving is different.
When I mentioned "messy" I meant just copying and pasting the code into the forum, use
Code:
tags next time so it formats perfectly! :good::highfive:
Click to expand...
Click to collapse
Thank you !
Cooper.G said:
Thank you for your patient.
1. I tried your code, and I was wrong about the permission, it says PERMISSION_DENIED. but I think this is not the problem for this question.
2. Did you tried my code ? The way that I asked for "WRITE_SETTINGS" is really work for ringtone, altho
Java:
private boolean checkWriteSettingsPermissions() {
String permission = "android.permission.WRITE_SETTINGS";
int res = getContext().checkCallingOrSelfPermission(permission);
return (res == PackageManager.PERMISSION_GRANTED);
}
said "PERMISSION_DENIED" , but it's really changed the ringtone ! If you not believe this, please try by yourself, and you can see from the setting - ring and vibrate - ringtone , you can see the result.
3. After several times try, I figure it out now... both way(manual and auto set by code "setMyRingtone()") of set the ringtone will work on the phone if have the permission of "Settings.System.canWrite(this)", but only work for the Ringtone of SIM 1, not work for SIM2. you can see the result form the setting page(only the ringtone for sim1 will change). if the ringtone still play the default ring of system, the problem probably is the metter of URI .
4. Before I post this thread, both way won't change the result of ringtone from the setting page of the phone, but as I said , you can see the result form another third part application.(this problem most probably is that I only use one SIM card at that time, did I put it into sim2? I don't know, already forget... but now if I put it into sim2 the ringtone form the setting page of the phone never change, but from the log of the code you can see the result is correct actually.)
5. Now the problem change into "How to create a standard URI and how to change the ringtone for SIM2". I will try to work on it.
6. Sorry for my pool English, and sorry for the "messy" code, I will improve it.
Anyway , thank you. you r the only one who helped me... Wish u luck.
Click to expand...
Click to collapse
Hey Have you found the solution..?

error: package com.google.android.maps does not exist

Hi,
i develop a map-app and want to implement google maps search
i get following build error
"error: package com.google.android.maps does not exist"
i develop under "android studio 3.1.3"
Hint for solution were appreciated
thanks
You need to add a reference to the maps package in build.gradle
Sent from my Z2_PRO using Tapatalk
i tested this https://stackoverflow.com/questions...le-android-maps-does-not-exist-android-studio
but without success
Can you post the content of your build.gradle file?
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.tux.myapplication"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0-alpha3'
implementation 'com.google.android.gmslay-services-maps:15.0.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
elvis61 said:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.tux.myapplication"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0-alpha3'
implementation 'com.google.android.gmslay-services-maps:15.0.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
Click to expand...
Click to collapse
Apologies for the late reply, didn't get a notification from the thread.
Try removing the lines:
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.android.gmslay-services-maps:15.0.1
And add
implementation 'com.google.android.gmslay-services-maps:16.0.0'
If that doesn't work I'll draw up a demo app - this is a bit odd as I'm actually using maps in an app for my uni coursework and it's working fine
Edit: Also check that you have added the Google maven repo in the top level build.gradle file
hi,
i have still same error. i explained abov my purpose. i try this suggestion
https://stackoverflow.com/questions...ment-google-maps-search-by-address-in-android
and get this error.
and here is next purpose
https://stackoverflow.com/questions...-name-on-google-map-android?noredirect=1&lq=1
i don't know which one is better. i mean which one i can build without error.
hi jonny,
i have now a version it can work for me. but any thing is missed. can you pls add the missing parts.
thanks
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
@override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker and move the camera
setContentView(R.layout.activity_place);
EditText geoName = (EditText) findViewById(R.id.geoName);
String sGeoName = geoName.getText().toString();
LatLng geoPlace = getLocationFromAddress(this, sGeoName);
mMap.addMarker(new MarkerOptions().position(geoPlace).title(sGeoName));
mMap.moveCamera(CameraUpdateFactory.newLatLng(geoPlace));
}
/**
*
* @param context
* @param strAddress
* @return
*/
public LatLng getLocationFromAddress(Context context, String strAddress) {
Geocoder coder = new Geocoder(context);
List<Address> address;
LatLng p1 = null;
try {
// May throw an IOException
address = coder.getFromLocationName(strAddress, 5);
if (address == null) {
return null;
}
Address location = address.get(0);
p1 = new LatLng(location.getLatitude(), location.getLongitude());
} catch (IOException ex) {
ex.printStackTrace();
}
return p1;
}
}
hi jonny,
i have now a version it can work for me. but any thing is missed. can you pls add the missing parts.
thanks
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
@override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker and move the camera
setContentView(R.layout.activity_place);
EditText geoName = (EditText) findViewById(R.id.geoName);
String sGeoName = geoName.getText().toString();
LatLng geoPlace = getLocationFromAddress(this, sGeoName);
mMap.addMarker(new MarkerOptions().position(geoPlace).title(sGeoName));
mMap.moveCamera(CameraUpdateFactory.newLatLng(geoPlace));
}
/**
*
* @param context
* @param strAddress
* @return
*/
public LatLng getLocationFromAddress(Context context, String strAddress) {
Geocoder coder = new Geocoder(context);
List<Address> address;
LatLng p1 = null;
try {
// May throw an IOException
address = coder.getFromLocationName(strAddress, 5);
if (address == null) {
return null;
}
Address location = address.get(0);
p1 = new LatLng(location.getLatitude(), location.getLongitude());
} catch (IOException ex) {
ex.printStackTrace();
}
return p1;
}
}
briefly i will edit place name and move the camera. easy. but not for a newbie. pls support me.

Categories

Resources